Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions processmanager/ebpf/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package ebpf // import "go.opentelemetry.io/ebpf-profiler/processmanager/ebpf"

/*
#include <stdint.h>
#include "../../support/ebpf/types.h"
*/
import "C"

import (
"fmt"

"go.opentelemetry.io/ebpf-profiler/host"
"go.opentelemetry.io/ebpf-profiler/interpreter"
"go.opentelemetry.io/ebpf-profiler/libpf"
"go.opentelemetry.io/ebpf-profiler/lpm"
"go.opentelemetry.io/ebpf-profiler/metrics"
"go.opentelemetry.io/ebpf-profiler/nativeunwind/stackdeltatypes"
"go.opentelemetry.io/ebpf-profiler/util"
)

// EbpfHandler provides the functionality to interact with eBPF maps.
type EbpfHandler interface {
// Embed interpreter.EbpfHandler as subset of this interface.
interpreter.EbpfHandler

// RemoveReportedPID removes a PID from the reported_pids eBPF map.
RemoveReportedPID(pid libpf.PID)

// UpdateUnwindInfo writes UnwindInfo to given unwind info array index
UpdateUnwindInfo(index uint16, info stackdeltatypes.UnwindInfo) error

// UpdateExeIDToStackDeltas defines a function that updates the eBPF map exe_id_to_stack_deltas
// for host.FileID with the elements of StackDeltaEBPF. It returns the mapID used.
UpdateExeIDToStackDeltas(fileID host.FileID, deltas []StackDeltaEBPF) (uint16, error)

// DeleteExeIDToStackDeltas defines a function that removes the entries from the outer eBPF
// map exe_id_to_stack_deltas and its associated inner map entries.
DeleteExeIDToStackDeltas(fileID host.FileID, mapID uint16) error

// UpdateStackDeltaPages defines a function that updates the mapping in a eBPF map from
// a FileID and page to its stack delta lookup information.
UpdateStackDeltaPages(fileID host.FileID, numDeltasPerPage []uint16,
mapID uint16, firstPageAddr uint64) error

// DeleteStackDeltaPage defines a function that removes the element specified by fileID and page
// from the eBPF map.
DeleteStackDeltaPage(fileID host.FileID, page uint64) error

// UpdatePidPageMappingInfo defines a function that updates the eBPF map
// pid_page_to_mapping_info with the given pidAndPage and fileIDAndOffset encoded values
// as key/value pair.
UpdatePidPageMappingInfo(pid libpf.PID, prefix lpm.Prefix, fileID, bias uint64) error

// DeletePidPageMappingInfo removes the elements specified by prefixes from eBPF map
// pid_page_to_mapping_info and returns the number of elements removed.
DeletePidPageMappingInfo(pid libpf.PID, prefixes []lpm.Prefix) (int, error)

// CollectMetrics returns gathered errors for changes to eBPF maps.
CollectMetrics() []metrics.Metric

// SupportsGenericBatchOperations returns true if the kernel supports eBPF batch operations
// on hash and array maps.
SupportsGenericBatchOperations() bool

// SupportsLPMTrieBatchOperations returns true if the kernel supports eBPF batch operations
// on LPM trie maps.
SupportsLPMTrieBatchOperations() bool
}

// StackDeltaEBPF represents stack deltas preprocessed by the ProcessManager which are
// then loaded to the eBPF map. This is Go equivalent of 'struct StackDelta' in eBPF types.h.
// See the eBPF header file for details.
type StackDeltaEBPF struct {
AddressLow uint16
UnwindInfo uint16
}

func InterpreterOffsetKeyValue(ebpfProgIndex uint16, fileID host.FileID,
offsetRanges []util.Range) (key uint64, value C.OffsetRange, err error) {
rLen := len(offsetRanges)
if rLen < 1 || rLen > 2 {
return 0, C.OffsetRange{}, fmt.Errorf("invalid ranges %v", offsetRanges)
}
// The keys of this map are executable-id-and-offset-into-text entries, and
// the offset_range associated with them gives the precise area in that page
// where the main interpreter loop is located. This is required to unwind
// nicely from native code into interpreted code.
key = uint64(fileID)
first := offsetRanges[0]
value = C.OffsetRange{
lower_offset1: C.u64(first.Start),
upper_offset1: C.u64(first.End),
program_index: C.u16(ebpfProgIndex),
}
if len(offsetRanges) == 2 {
// Fields {lower,upper}_offset2 may be used to specify an optional second range
// of an interpreter function. This may be useful if the interpreter function
// consists of two non-contiguous memory ranges, which may happen due to Hot/Cold
// split compiler optimization
second := offsetRanges[1]
value.lower_offset2 = C.u64(second.Start)
value.upper_offset2 = C.u64(second.End)
}
return key, value, nil
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package ebpf // import "go.opentelemetry.io/ebpf-profiler/processmanager/ebpf"
package impl // import "go.opentelemetry.io/ebpf-profiler/processmanager/ebpf"

import (
"context"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package ebpf
package impl

import (
"context"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package ebpf // import "go.opentelemetry.io/ebpf-profiler/processmanager/ebpf"
package impl // import "go.opentelemetry.io/ebpf-profiler/processmanager/ebpf"

import (
"context"
Expand All @@ -15,11 +15,11 @@
"github.com/cilium/ebpf/features"
log "github.com/sirupsen/logrus"
"go.opentelemetry.io/ebpf-profiler/host"
"go.opentelemetry.io/ebpf-profiler/interpreter"
"go.opentelemetry.io/ebpf-profiler/libpf"
"go.opentelemetry.io/ebpf-profiler/lpm"
"go.opentelemetry.io/ebpf-profiler/metrics"
sdtypes "go.opentelemetry.io/ebpf-profiler/nativeunwind/stackdeltatypes"
"go.opentelemetry.io/ebpf-profiler/processmanager/ebpf"
"go.opentelemetry.io/ebpf-profiler/rlimit"
"go.opentelemetry.io/ebpf-profiler/support"
"go.opentelemetry.io/ebpf-profiler/util"
Expand All @@ -28,7 +28,7 @@

/*
#include <stdint.h>
#include "../../support/ebpf/types.h"
#include "../../../support/ebpf/types.h"
*/
import "C"

Expand All @@ -40,55 +40,6 @@
updatePoolQueueCap = 8
)

// EbpfHandler provides the functionality to interact with eBPF maps.
type EbpfHandler interface {
// Embed interpreter.EbpfHandler as subset of this interface.
interpreter.EbpfHandler

// RemoveReportedPID removes a PID from the reported_pids eBPF map.
RemoveReportedPID(pid libpf.PID)

// UpdateUnwindInfo writes UnwindInfo to given unwind info array index
UpdateUnwindInfo(index uint16, info sdtypes.UnwindInfo) error

// UpdateExeIDToStackDeltas defines a function that updates the eBPF map exe_id_to_stack_deltas
// for host.FileID with the elements of StackDeltaEBPF. It returns the mapID used.
UpdateExeIDToStackDeltas(fileID host.FileID, deltas []StackDeltaEBPF) (uint16, error)

// DeleteExeIDToStackDeltas defines a function that removes the entries from the outer eBPF
// map exe_id_to_stack_deltas and its associated inner map entries.
DeleteExeIDToStackDeltas(fileID host.FileID, mapID uint16) error

// UpdateStackDeltaPages defines a function that updates the mapping in a eBPF map from
// a FileID and page to its stack delta lookup information.
UpdateStackDeltaPages(fileID host.FileID, numDeltasPerPage []uint16,
mapID uint16, firstPageAddr uint64) error

// DeleteStackDeltaPage defines a function that removes the element specified by fileID and page
// from the eBPF map.
DeleteStackDeltaPage(fileID host.FileID, page uint64) error

// UpdatePidPageMappingInfo defines a function that updates the eBPF map
// pid_page_to_mapping_info with the given pidAndPage and fileIDAndOffset encoded values
// as key/value pair.
UpdatePidPageMappingInfo(pid libpf.PID, prefix lpm.Prefix, fileID, bias uint64) error

// DeletePidPageMappingInfo removes the elements specified by prefixes from eBPF map
// pid_page_to_mapping_info and returns the number of elements removed.
DeletePidPageMappingInfo(pid libpf.PID, prefixes []lpm.Prefix) (int, error)

// CollectMetrics returns gathered errors for changes to eBPF maps.
CollectMetrics() []metrics.Metric

// SupportsGenericBatchOperations returns true if the kernel supports eBPF batch operations
// on hash and array maps.
SupportsGenericBatchOperations() bool

// SupportsLPMTrieBatchOperations returns true if the kernel supports eBPF batch operations
// on LPM trie maps.
SupportsLPMTrieBatchOperations() bool
}

type ebpfMapsImpl struct {
// Interpreter related eBPF maps
interpreterOffsets *cebpf.Map
Expand Down Expand Up @@ -138,14 +89,14 @@
}

// Compile time check to make sure ebpfMapsImpl satisfies the interface .
var _ EbpfHandler = &ebpfMapsImpl{}
var _ ebpf.EbpfHandler = &ebpfMapsImpl{}

// LoadMaps checks if the needed maps for the process manager are available
// and loads their references into a package-internal structure.
//
// It further spawns background workers for deferred map updates; the given
// context can be used to terminate them on shutdown.
func LoadMaps(ctx context.Context, maps map[string]*cebpf.Map) (EbpfHandler, error) {
func LoadMaps(ctx context.Context, maps map[string]*cebpf.Map) (ebpf.EbpfHandler, error) {
impl := &ebpfMapsImpl{}
impl.errCounter = make(map[metrics.MetricID]int64)

Expand Down Expand Up @@ -256,7 +207,7 @@
// UpdateInterpreterOffsets adds the given moduleRanges to the eBPF map interpreterOffsets.
func (impl *ebpfMapsImpl) UpdateInterpreterOffsets(ebpfProgIndex uint16, fileID host.FileID,
offsetRanges []util.Range) error {
key, value, err := InterpreterOffsetKeyValue(ebpfProgIndex, fileID, offsetRanges)
key, value, err := ebpf.InterpreterOffsetKeyValue(ebpfProgIndex, fileID, offsetRanges)
if err != nil {
return err
}
Expand All @@ -268,35 +219,6 @@
return nil
}

func InterpreterOffsetKeyValue(ebpfProgIndex uint16, fileID host.FileID,
offsetRanges []util.Range) (key uint64, value C.OffsetRange, err error) {
rLen := len(offsetRanges)
if rLen < 1 || rLen > 2 {
return 0, C.OffsetRange{}, fmt.Errorf("invalid ranges %v", offsetRanges)
}
// The keys of this map are executable-id-and-offset-into-text entries, and
// the offset_range associated with them gives the precise area in that page
// where the main interpreter loop is located. This is required to unwind
// nicely from native code into interpreted code.
key = uint64(fileID)
first := offsetRanges[0]
value = C.OffsetRange{
lower_offset1: C.u64(first.Start),
upper_offset1: C.u64(first.End),
program_index: C.u16(ebpfProgIndex),
}
if len(offsetRanges) == 2 {
// Fields {lower,upper}_offset2 may be used to specify an optional second range
// of an interpreter function. This may be useful if the interpreter function
// consists of two non-contiguous memory ranges, which may happen due to Hot/Cold
// split compiler optimization
second := offsetRanges[1]
value.lower_offset2 = C.u64(second.Start)
value.upper_offset2 = C.u64(second.End)
}
return key, value, nil
}

// getInterpreterTypeMap returns the eBPF map for the given typ
// or an error if typ is not supported.
func (impl *ebpfMapsImpl) getInterpreterTypeMap(typ libpf.InterpreterType) (*cebpf.Map, error) {
Expand Down Expand Up @@ -592,7 +514,7 @@

// UpdateExeIDToStackDeltas creates a nested map for fileID in the eBPF map exeIDTostack_deltas
// and inserts the elements of the deltas array in this nested map. Returns mapID or error.
func (impl *ebpfMapsImpl) UpdateExeIDToStackDeltas(fileID host.FileID, deltas []StackDeltaEBPF) (
func (impl *ebpfMapsImpl) UpdateExeIDToStackDeltas(fileID host.FileID, deltas []ebpf.StackDeltaEBPF) (
uint16, error) {
numDeltas := len(deltas)
mapID, err := getMapID(uint32(numDeltas))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package ebpf
package impl

import (
"testing"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package ebpf
package impl

import (
"fmt"
Expand Down
12 changes: 0 additions & 12 deletions processmanager/ebpf/types.go

This file was deleted.

2 changes: 1 addition & 1 deletion tracer/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (
"go.opentelemetry.io/ebpf-profiler/nativeunwind/elfunwindinfo"
"go.opentelemetry.io/ebpf-profiler/periodiccaller"
pm "go.opentelemetry.io/ebpf-profiler/processmanager"
pmebpf "go.opentelemetry.io/ebpf-profiler/processmanager/ebpf"
pmebpf "go.opentelemetry.io/ebpf-profiler/processmanager/ebpf/impl"
"go.opentelemetry.io/ebpf-profiler/reporter"
"go.opentelemetry.io/ebpf-profiler/rlimit"
"go.opentelemetry.io/ebpf-profiler/support"
Expand Down
Loading