vendor: update google/cadvisor and opencontainers/runc
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
403
vendor/github.com/cilium/ebpf/map.go
generated
vendored
403
vendor/github.com/cilium/ebpf/map.go
generated
vendored
@@ -2,14 +2,25 @@ package ebpf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
"strings"
|
||||
|
||||
"github.com/cilium/ebpf/internal"
|
||||
"github.com/cilium/ebpf/internal/btf"
|
||||
"github.com/cilium/ebpf/internal/unix"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
// Errors returned by Map and MapIterator methods.
|
||||
var (
|
||||
ErrKeyNotExist = xerrors.New("key does not exist")
|
||||
ErrKeyExist = xerrors.New("key already exists")
|
||||
ErrIterationAborted = xerrors.New("iteration aborted")
|
||||
)
|
||||
|
||||
// MapID represents the unique ID of an eBPF map
|
||||
type MapID uint32
|
||||
|
||||
// MapSpec defines a Map.
|
||||
type MapSpec struct {
|
||||
// Name is passed to the kernel as a debug aid. Must only contain
|
||||
@@ -20,8 +31,18 @@ type MapSpec struct {
|
||||
ValueSize uint32
|
||||
MaxEntries uint32
|
||||
Flags uint32
|
||||
|
||||
// The initial contents of the map. May be nil.
|
||||
Contents []MapKV
|
||||
|
||||
// Whether to freeze a map after setting its initial contents.
|
||||
Freeze bool
|
||||
|
||||
// InnerMap is used as a template for ArrayOfMaps and HashOfMaps
|
||||
InnerMap *MapSpec
|
||||
|
||||
// The BTF associated with this map.
|
||||
BTF *btf.Map
|
||||
}
|
||||
|
||||
func (ms *MapSpec) String() string {
|
||||
@@ -29,16 +50,26 @@ func (ms *MapSpec) String() string {
|
||||
}
|
||||
|
||||
// Copy returns a copy of the spec.
|
||||
//
|
||||
// MapSpec.Contents is a shallow copy.
|
||||
func (ms *MapSpec) Copy() *MapSpec {
|
||||
if ms == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
cpy := *ms
|
||||
cpy.Contents = make([]MapKV, len(ms.Contents))
|
||||
copy(cpy.Contents, ms.Contents)
|
||||
cpy.InnerMap = ms.InnerMap.Copy()
|
||||
return &cpy
|
||||
}
|
||||
|
||||
// MapKV is used to initialize the contents of a Map.
|
||||
type MapKV struct {
|
||||
Key interface{}
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
// Map represents a Map file descriptor.
|
||||
//
|
||||
// It is not safe to close a map which is used by other goroutines.
|
||||
@@ -50,7 +81,7 @@ func (ms *MapSpec) Copy() *MapSpec {
|
||||
// if you require custom encoding.
|
||||
type Map struct {
|
||||
name string
|
||||
fd *bpfFD
|
||||
fd *internal.FD
|
||||
abi MapABI
|
||||
// Per CPU maps return values larger than the size in the spec
|
||||
fullValueSize int
|
||||
@@ -61,13 +92,13 @@ type Map struct {
|
||||
// You should not use fd after calling this function.
|
||||
func NewMapFromFD(fd int) (*Map, error) {
|
||||
if fd < 0 {
|
||||
return nil, errors.New("invalid fd")
|
||||
return nil, xerrors.New("invalid fd")
|
||||
}
|
||||
bpfFd := newBPFFD(uint32(fd))
|
||||
bpfFd := internal.NewFD(uint32(fd))
|
||||
|
||||
name, abi, err := newMapABIFromFd(bpfFd)
|
||||
if err != nil {
|
||||
bpfFd.forget()
|
||||
bpfFd.Forget()
|
||||
return nil, err
|
||||
}
|
||||
return newMap(bpfFd, name, abi)
|
||||
@@ -77,89 +108,135 @@ func NewMapFromFD(fd int) (*Map, error) {
|
||||
//
|
||||
// Creating a map for the first time will perform feature detection
|
||||
// by creating small, temporary maps.
|
||||
//
|
||||
// The caller is responsible for ensuring the process' rlimit is set
|
||||
// sufficiently high for locking memory during map creation. This can be done
|
||||
// by calling unix.Setrlimit with unix.RLIMIT_MEMLOCK prior to calling NewMap.
|
||||
func NewMap(spec *MapSpec) (*Map, error) {
|
||||
if spec.BTF == nil {
|
||||
return newMapWithBTF(spec, nil)
|
||||
}
|
||||
|
||||
handle, err := btf.NewHandle(btf.MapSpec(spec.BTF))
|
||||
if err != nil && !xerrors.Is(err, btf.ErrNotSupported) {
|
||||
return nil, xerrors.Errorf("can't load BTF: %w", err)
|
||||
}
|
||||
|
||||
return newMapWithBTF(spec, handle)
|
||||
}
|
||||
|
||||
func newMapWithBTF(spec *MapSpec, handle *btf.Handle) (*Map, error) {
|
||||
if spec.Type != ArrayOfMaps && spec.Type != HashOfMaps {
|
||||
return createMap(spec, nil)
|
||||
return createMap(spec, nil, handle)
|
||||
}
|
||||
|
||||
if spec.InnerMap == nil {
|
||||
return nil, errors.Errorf("%s requires InnerMap", spec.Type)
|
||||
return nil, xerrors.Errorf("%s requires InnerMap", spec.Type)
|
||||
}
|
||||
|
||||
template, err := createMap(spec.InnerMap, nil)
|
||||
template, err := createMap(spec.InnerMap, nil, handle)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer template.Close()
|
||||
|
||||
return createMap(spec, template.fd)
|
||||
return createMap(spec, template.fd, handle)
|
||||
}
|
||||
|
||||
func createMap(spec *MapSpec, inner *bpfFD) (*Map, error) {
|
||||
spec = spec.Copy()
|
||||
func createMap(spec *MapSpec, inner *internal.FD, handle *btf.Handle) (*Map, error) {
|
||||
abi := newMapABIFromSpec(spec)
|
||||
|
||||
switch spec.Type {
|
||||
case ArrayOfMaps:
|
||||
fallthrough
|
||||
case HashOfMaps:
|
||||
if spec.ValueSize != 0 && spec.ValueSize != 4 {
|
||||
return nil, errors.Errorf("ValueSize must be zero or four for map of map")
|
||||
if err := haveNestedMaps(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
spec.ValueSize = 4
|
||||
|
||||
if abi.ValueSize != 0 && abi.ValueSize != 4 {
|
||||
return nil, xerrors.New("ValueSize must be zero or four for map of map")
|
||||
}
|
||||
abi.ValueSize = 4
|
||||
|
||||
case PerfEventArray:
|
||||
if spec.KeySize != 0 {
|
||||
return nil, errors.Errorf("KeySize must be zero for perf event array")
|
||||
}
|
||||
if spec.ValueSize != 0 {
|
||||
return nil, errors.Errorf("ValueSize must be zero for perf event array")
|
||||
}
|
||||
if spec.MaxEntries == 0 {
|
||||
n, err := internal.OnlineCPUs()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "perf event array")
|
||||
}
|
||||
spec.MaxEntries = uint32(n)
|
||||
if abi.KeySize != 0 && abi.KeySize != 4 {
|
||||
return nil, xerrors.New("KeySize must be zero or four for perf event array")
|
||||
}
|
||||
abi.KeySize = 4
|
||||
|
||||
spec.KeySize = 4
|
||||
spec.ValueSize = 4
|
||||
if abi.ValueSize != 0 && abi.ValueSize != 4 {
|
||||
return nil, xerrors.New("ValueSize must be zero or four for perf event array")
|
||||
}
|
||||
abi.ValueSize = 4
|
||||
|
||||
if abi.MaxEntries == 0 {
|
||||
n, err := internal.PossibleCPUs()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("perf event array: %w", err)
|
||||
}
|
||||
abi.MaxEntries = uint32(n)
|
||||
}
|
||||
}
|
||||
|
||||
if abi.Flags&(unix.BPF_F_RDONLY_PROG|unix.BPF_F_WRONLY_PROG) > 0 || spec.Freeze {
|
||||
if err := haveMapMutabilityModifiers(); err != nil {
|
||||
return nil, xerrors.Errorf("map create: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
attr := bpfMapCreateAttr{
|
||||
mapType: spec.Type,
|
||||
keySize: spec.KeySize,
|
||||
valueSize: spec.ValueSize,
|
||||
maxEntries: spec.MaxEntries,
|
||||
flags: spec.Flags,
|
||||
mapType: abi.Type,
|
||||
keySize: abi.KeySize,
|
||||
valueSize: abi.ValueSize,
|
||||
maxEntries: abi.MaxEntries,
|
||||
flags: abi.Flags,
|
||||
}
|
||||
|
||||
if inner != nil {
|
||||
var err error
|
||||
attr.innerMapFd, err = inner.value()
|
||||
attr.innerMapFd, err = inner.Value()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "map create")
|
||||
return nil, xerrors.Errorf("map create: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
name, err := newBPFObjName(spec.Name)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "map create")
|
||||
if handle != nil && spec.BTF != nil {
|
||||
attr.btfFd = uint32(handle.FD())
|
||||
attr.btfKeyTypeID = btf.MapKey(spec.BTF).ID()
|
||||
attr.btfValueTypeID = btf.MapValue(spec.BTF).ID()
|
||||
}
|
||||
|
||||
if haveObjName.Result() {
|
||||
attr.mapName = name
|
||||
if haveObjName() == nil {
|
||||
attr.mapName = newBPFObjName(spec.Name)
|
||||
}
|
||||
|
||||
fd, err := bpfMapCreate(&attr)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "map create")
|
||||
return nil, xerrors.Errorf("map create: %w", err)
|
||||
}
|
||||
|
||||
return newMap(fd, spec.Name, newMapABIFromSpec(spec))
|
||||
m, err := newMap(fd, spec.Name, abi)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := m.populate(spec.Contents); err != nil {
|
||||
m.Close()
|
||||
return nil, xerrors.Errorf("map create: can't set initial contents: %w", err)
|
||||
}
|
||||
|
||||
if spec.Freeze {
|
||||
if err := m.Freeze(); err != nil {
|
||||
m.Close()
|
||||
return nil, xerrors.Errorf("can't freeze map: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func newMap(fd *bpfFD, name string, abi *MapABI) (*Map, error) {
|
||||
func newMap(fd *internal.FD, name string, abi *MapABI) (*Map, error) {
|
||||
m := &Map{
|
||||
name,
|
||||
fd,
|
||||
@@ -224,9 +301,9 @@ func (m *Map) Lookup(key, valueOut interface{}) error {
|
||||
*value = m
|
||||
return nil
|
||||
case *Map:
|
||||
return errors.Errorf("can't unmarshal into %T, need %T", value, (**Map)(nil))
|
||||
return xerrors.Errorf("can't unmarshal into %T, need %T", value, (**Map)(nil))
|
||||
case Map:
|
||||
return errors.Errorf("can't unmarshal into %T, need %T", value, (**Map)(nil))
|
||||
return xerrors.Errorf("can't unmarshal into %T, need %T", value, (**Map)(nil))
|
||||
|
||||
case **Program:
|
||||
p, err := unmarshalProgram(valueBytes)
|
||||
@@ -238,38 +315,58 @@ func (m *Map) Lookup(key, valueOut interface{}) error {
|
||||
*value = p
|
||||
return nil
|
||||
case *Program:
|
||||
return errors.Errorf("can't unmarshal into %T, need %T", value, (**Program)(nil))
|
||||
return xerrors.Errorf("can't unmarshal into %T, need %T", value, (**Program)(nil))
|
||||
case Program:
|
||||
return errors.Errorf("can't unmarshal into %T, need %T", value, (**Program)(nil))
|
||||
return xerrors.Errorf("can't unmarshal into %T, need %T", value, (**Program)(nil))
|
||||
|
||||
default:
|
||||
return unmarshalBytes(valueOut, valueBytes)
|
||||
}
|
||||
}
|
||||
|
||||
// LookupAndDelete retrieves and deletes a value from a Map.
|
||||
//
|
||||
// Returns ErrKeyNotExist if the key doesn't exist.
|
||||
func (m *Map) LookupAndDelete(key, valueOut interface{}) error {
|
||||
valuePtr, valueBytes := makeBuffer(valueOut, m.fullValueSize)
|
||||
|
||||
keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("can't marshal key: %w", err)
|
||||
}
|
||||
|
||||
if err := bpfMapLookupAndDelete(m.fd, keyPtr, valuePtr); err != nil {
|
||||
return xerrors.Errorf("lookup and delete failed: %w", err)
|
||||
}
|
||||
|
||||
return unmarshalBytes(valueOut, valueBytes)
|
||||
}
|
||||
|
||||
// LookupBytes gets a value from Map.
|
||||
//
|
||||
// Returns a nil value if a key doesn't exist.
|
||||
func (m *Map) LookupBytes(key interface{}) ([]byte, error) {
|
||||
valueBytes := make([]byte, m.fullValueSize)
|
||||
valuePtr := newPtr(unsafe.Pointer(&valueBytes[0]))
|
||||
valuePtr := internal.NewSlicePointer(valueBytes)
|
||||
|
||||
err := m.lookup(key, valuePtr)
|
||||
if IsNotExist(err) {
|
||||
if xerrors.Is(err, ErrKeyNotExist) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return valueBytes, err
|
||||
}
|
||||
|
||||
func (m *Map) lookup(key interface{}, valueOut syscallPtr) error {
|
||||
func (m *Map) lookup(key interface{}, valueOut internal.Pointer) error {
|
||||
keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
|
||||
if err != nil {
|
||||
return errors.WithMessage(err, "can't marshal key")
|
||||
return xerrors.Errorf("can't marshal key: %w", err)
|
||||
}
|
||||
|
||||
err = bpfMapLookupElem(m.fd, keyPtr, valueOut)
|
||||
return errors.WithMessage(err, "lookup failed")
|
||||
if err = bpfMapLookupElem(m.fd, keyPtr, valueOut); err != nil {
|
||||
return xerrors.Errorf("lookup failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MapUpdateFlags controls the behaviour of the Map.Update call.
|
||||
@@ -297,38 +394,46 @@ func (m *Map) Put(key, value interface{}) error {
|
||||
func (m *Map) Update(key, value interface{}, flags MapUpdateFlags) error {
|
||||
keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
|
||||
if err != nil {
|
||||
return errors.WithMessage(err, "can't marshal key")
|
||||
return xerrors.Errorf("can't marshal key: %w", err)
|
||||
}
|
||||
|
||||
var valuePtr syscallPtr
|
||||
var valuePtr internal.Pointer
|
||||
if m.abi.Type.hasPerCPUValue() {
|
||||
valuePtr, err = marshalPerCPUValue(value, int(m.abi.ValueSize))
|
||||
} else {
|
||||
valuePtr, err = marshalPtr(value, int(m.abi.ValueSize))
|
||||
}
|
||||
if err != nil {
|
||||
return errors.WithMessage(err, "can't marshal value")
|
||||
return xerrors.Errorf("can't marshal value: %w", err)
|
||||
}
|
||||
|
||||
return bpfMapUpdateElem(m.fd, keyPtr, valuePtr, uint64(flags))
|
||||
if err = bpfMapUpdateElem(m.fd, keyPtr, valuePtr, uint64(flags)); err != nil {
|
||||
return xerrors.Errorf("update failed: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete removes a value.
|
||||
//
|
||||
// Returns an error if the key does not exist, see IsNotExist.
|
||||
// Returns ErrKeyNotExist if the key does not exist.
|
||||
func (m *Map) Delete(key interface{}) error {
|
||||
keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
|
||||
if err != nil {
|
||||
return errors.WithMessage(err, "can't marshal key")
|
||||
return xerrors.Errorf("can't marshal key: %w", err)
|
||||
}
|
||||
|
||||
err = bpfMapDeleteElem(m.fd, keyPtr)
|
||||
return errors.WithMessage(err, "can't delete key")
|
||||
if err = bpfMapDeleteElem(m.fd, keyPtr); err != nil {
|
||||
return xerrors.Errorf("delete failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NextKey finds the key following an initial key.
|
||||
//
|
||||
// See NextKeyBytes for details.
|
||||
//
|
||||
// Returns ErrKeyNotExist if there is no next key.
|
||||
func (m *Map) NextKey(key, nextKeyOut interface{}) error {
|
||||
nextKeyPtr, nextKeyBytes := makeBuffer(nextKeyOut, int(m.abi.KeySize))
|
||||
|
||||
@@ -340,8 +445,10 @@ func (m *Map) NextKey(key, nextKeyOut interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := unmarshalBytes(nextKeyOut, nextKeyBytes)
|
||||
return errors.WithMessage(err, "can't unmarshal next key")
|
||||
if err := unmarshalBytes(nextKeyOut, nextKeyBytes); err != nil {
|
||||
return xerrors.Errorf("can't unmarshal next key: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NextKeyBytes returns the key following an initial key as a byte slice.
|
||||
@@ -349,33 +456,37 @@ func (m *Map) NextKey(key, nextKeyOut interface{}) error {
|
||||
// Passing nil will return the first key.
|
||||
//
|
||||
// Use Iterate if you want to traverse all entries in the map.
|
||||
//
|
||||
// Returns nil if there are no more keys.
|
||||
func (m *Map) NextKeyBytes(key interface{}) ([]byte, error) {
|
||||
nextKey := make([]byte, m.abi.KeySize)
|
||||
nextKeyPtr := newPtr(unsafe.Pointer(&nextKey[0]))
|
||||
nextKeyPtr := internal.NewSlicePointer(nextKey)
|
||||
|
||||
err := m.nextKey(key, nextKeyPtr)
|
||||
if IsNotExist(err) {
|
||||
if xerrors.Is(err, ErrKeyNotExist) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return nextKey, err
|
||||
}
|
||||
|
||||
func (m *Map) nextKey(key interface{}, nextKeyOut syscallPtr) error {
|
||||
func (m *Map) nextKey(key interface{}, nextKeyOut internal.Pointer) error {
|
||||
var (
|
||||
keyPtr syscallPtr
|
||||
keyPtr internal.Pointer
|
||||
err error
|
||||
)
|
||||
|
||||
if key != nil {
|
||||
keyPtr, err = marshalPtr(key, int(m.abi.KeySize))
|
||||
if err != nil {
|
||||
return errors.WithMessage(err, "can't marshal key")
|
||||
return xerrors.Errorf("can't marshal key: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
err = bpfMapGetNextKey(m.fd, keyPtr, nextKeyOut)
|
||||
return errors.WithMessage(err, "can't get next key")
|
||||
if err = bpfMapGetNextKey(m.fd, keyPtr, nextKeyOut); err != nil {
|
||||
return xerrors.Errorf("next key failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Iterate traverses a map.
|
||||
@@ -396,14 +507,14 @@ func (m *Map) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
return m.fd.close()
|
||||
return m.fd.Close()
|
||||
}
|
||||
|
||||
// FD gets the file descriptor of the Map.
|
||||
//
|
||||
// Calling this function is invalid after Close has been called.
|
||||
func (m *Map) FD() int {
|
||||
fd, err := m.fd.value()
|
||||
fd, err := m.fd.Value()
|
||||
if err != nil {
|
||||
// Best effort: -1 is the number most likely to be an
|
||||
// invalid file descriptor.
|
||||
@@ -424,9 +535,9 @@ func (m *Map) Clone() (*Map, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
dup, err := m.fd.dup()
|
||||
dup, err := m.fd.Dup()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "can't clone map")
|
||||
return nil, xerrors.Errorf("can't clone map: %w", err)
|
||||
}
|
||||
|
||||
return newMap(dup, m.name, &m.abi)
|
||||
@@ -439,6 +550,29 @@ func (m *Map) Pin(fileName string) error {
|
||||
return bpfPinObject(fileName, m.fd)
|
||||
}
|
||||
|
||||
// Freeze prevents a map to be modified from user space.
|
||||
//
|
||||
// It makes no changes to kernel-side restrictions.
|
||||
func (m *Map) Freeze() error {
|
||||
if err := haveMapMutabilityModifiers(); err != nil {
|
||||
return xerrors.Errorf("can't freeze map: %w", err)
|
||||
}
|
||||
|
||||
if err := bpfMapFreeze(m.fd); err != nil {
|
||||
return xerrors.Errorf("can't freeze map: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Map) populate(contents []MapKV) error {
|
||||
for _, kv := range contents {
|
||||
if err := m.Put(kv.Key, kv.Value); err != nil {
|
||||
return xerrors.Errorf("key %v: %w", kv.Key, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadPinnedMap load a Map from a BPF file.
|
||||
//
|
||||
// The function is not compatible with nested maps.
|
||||
@@ -450,7 +584,7 @@ func LoadPinnedMap(fileName string) (*Map, error) {
|
||||
}
|
||||
name, abi, err := newMapABIFromFd(fd)
|
||||
if err != nil {
|
||||
_ = fd.close()
|
||||
_ = fd.Close()
|
||||
return nil, err
|
||||
}
|
||||
return newMap(fd, name, abi)
|
||||
@@ -467,29 +601,18 @@ func LoadPinnedMapExplicit(fileName string, abi *MapABI) (*Map, error) {
|
||||
|
||||
func unmarshalMap(buf []byte) (*Map, error) {
|
||||
if len(buf) != 4 {
|
||||
return nil, errors.New("map id requires 4 byte value")
|
||||
return nil, xerrors.New("map id requires 4 byte value")
|
||||
}
|
||||
|
||||
// Looking up an entry in a nested map or prog array returns an id,
|
||||
// not an fd.
|
||||
id := internal.NativeEndian.Uint32(buf)
|
||||
fd, err := bpfGetMapFDByID(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
name, abi, err := newMapABIFromFd(fd)
|
||||
if err != nil {
|
||||
_ = fd.close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newMap(fd, name, abi)
|
||||
return NewMapFromID(MapID(id))
|
||||
}
|
||||
|
||||
// MarshalBinary implements BinaryMarshaler.
|
||||
func (m *Map) MarshalBinary() ([]byte, error) {
|
||||
fd, err := m.fd.value()
|
||||
fd, err := m.fd.Value()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -499,6 +622,60 @@ func (m *Map) MarshalBinary() ([]byte, error) {
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func patchValue(value []byte, typ btf.Type, replacements map[string]interface{}) error {
|
||||
replaced := make(map[string]bool)
|
||||
replace := func(name string, offset, size int, replacement interface{}) error {
|
||||
if offset+size > len(value) {
|
||||
return xerrors.Errorf("%s: offset %d(+%d) is out of bounds", name, offset, size)
|
||||
}
|
||||
|
||||
buf, err := marshalBytes(replacement, size)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("marshal %s: %w", name, err)
|
||||
}
|
||||
|
||||
copy(value[offset:offset+size], buf)
|
||||
replaced[name] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
switch parent := typ.(type) {
|
||||
case *btf.Datasec:
|
||||
for _, secinfo := range parent.Vars {
|
||||
name := string(secinfo.Type.(*btf.Var).Name)
|
||||
replacement, ok := replacements[name]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
err := replace(name, int(secinfo.Offset), int(secinfo.Size), replacement)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return xerrors.Errorf("patching %T is not supported", typ)
|
||||
}
|
||||
|
||||
if len(replaced) == len(replacements) {
|
||||
return nil
|
||||
}
|
||||
|
||||
var missing []string
|
||||
for name := range replacements {
|
||||
if !replaced[name] {
|
||||
missing = append(missing, name)
|
||||
}
|
||||
}
|
||||
|
||||
if len(missing) == 1 {
|
||||
return xerrors.Errorf("unknown field: %s", missing[0])
|
||||
}
|
||||
|
||||
return xerrors.Errorf("unknown fields: %s", strings.Join(missing, ","))
|
||||
}
|
||||
|
||||
// MapIterator iterates a Map.
|
||||
//
|
||||
// See Map.Iterate.
|
||||
@@ -519,8 +696,6 @@ func newMapIterator(target *Map) *MapIterator {
|
||||
}
|
||||
}
|
||||
|
||||
var errIterationAborted = errors.New("iteration aborted")
|
||||
|
||||
// Next decodes the next key and value.
|
||||
//
|
||||
// Iterating a hash map from which keys are being deleted is not
|
||||
@@ -556,7 +731,7 @@ func (mi *MapIterator) Next(keyOut, valueOut interface{}) bool {
|
||||
mi.prevKey = mi.prevBytes
|
||||
|
||||
mi.err = mi.target.Lookup(nextBytes, valueOut)
|
||||
if IsNotExist(mi.err) {
|
||||
if xerrors.Is(mi.err, ErrKeyNotExist) {
|
||||
// Even though the key should be valid, we couldn't look up
|
||||
// its value. If we're iterating a hash map this is probably
|
||||
// because a concurrent delete removed the value before we
|
||||
@@ -575,26 +750,50 @@ func (mi *MapIterator) Next(keyOut, valueOut interface{}) bool {
|
||||
return mi.err == nil
|
||||
}
|
||||
|
||||
mi.err = errIterationAborted
|
||||
mi.err = xerrors.Errorf("%w", ErrIterationAborted)
|
||||
return false
|
||||
}
|
||||
|
||||
// Err returns any encountered error.
|
||||
//
|
||||
// The method must be called after Next returns nil.
|
||||
//
|
||||
// Returns ErrIterationAborted if it wasn't possible to do a full iteration.
|
||||
func (mi *MapIterator) Err() error {
|
||||
return mi.err
|
||||
}
|
||||
|
||||
// IsNotExist returns true if the error indicates that a
|
||||
// key doesn't exist.
|
||||
func IsNotExist(err error) bool {
|
||||
return errors.Cause(err) == unix.ENOENT
|
||||
// MapGetNextID returns the ID of the next eBPF map.
|
||||
//
|
||||
// Returns ErrNotExist, if there is no next eBPF map.
|
||||
func MapGetNextID(startID MapID) (MapID, error) {
|
||||
id, err := objGetNextID(_MapGetNextID, uint32(startID))
|
||||
return MapID(id), err
|
||||
}
|
||||
|
||||
// IsIterationAborted returns true if the iteration was aborted.
|
||||
// NewMapFromID returns the map for a given id.
|
||||
//
|
||||
// This occurs when keys are deleted from a hash map during iteration.
|
||||
func IsIterationAborted(err error) bool {
|
||||
return errors.Cause(err) == errIterationAborted
|
||||
// Returns ErrNotExist, if there is no eBPF map with the given id.
|
||||
func NewMapFromID(id MapID) (*Map, error) {
|
||||
fd, err := bpfObjGetFDByID(_MapGetFDByID, uint32(id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
name, abi, err := newMapABIFromFd(fd)
|
||||
if err != nil {
|
||||
_ = fd.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newMap(fd, name, abi)
|
||||
}
|
||||
|
||||
// ID returns the systemwide unique ID of the map.
|
||||
func (m *Map) ID() (MapID, error) {
|
||||
info, err := bpfGetMapInfoByFD(m.fd)
|
||||
if err != nil {
|
||||
return MapID(0), err
|
||||
}
|
||||
return MapID(info.id), nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user