Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

internal: export BPFMapCreate syscall wrapper #325

Merged
merged 1 commit into from
Jun 15, 2021
Merged
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
35 changes: 35 additions & 0 deletions internal/syscall.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,38 @@ func BPFObjGetInfoByFD(fd *FD, info unsafe.Pointer, size uintptr) error {
}
return nil
}

// BPFObjName is a null-terminated string made up of
// 'A-Za-z0-9_' characters.
type BPFObjName [unix.BPF_OBJ_NAME_LEN]byte

// NewBPFObjName truncates the result if it is too long.
func NewBPFObjName(name string) BPFObjName {
var result BPFObjName
copy(result[:unix.BPF_OBJ_NAME_LEN-1], name)
return result
}

type BPFMapCreateAttr struct {
MapType uint32
KeySize uint32
ValueSize uint32
MaxEntries uint32
Flags uint32
InnerMapFd uint32 // since 4.12 56f668dfe00d
NumaNode uint32 // since 4.14 96eabe7a40aa
MapName BPFObjName // since 4.15 ad5b177bd73f
MapIfIndex uint32
BTFFd uint32
BTFKeyTypeID uint32
BTFValueTypeID uint32
}

func BPFMapCreate(attr *BPFMapCreateAttr) (*FD, error) {
fd, err := BPF(BPF_MAP_CREATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
if err != nil {
return nil, err
}

return NewFD(uint32(fd)), nil
}
17 changes: 17 additions & 0 deletions internal/syscall_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package internal

import (
"testing"

"github.com/cilium/ebpf/internal/unix"
)

func TestObjName(t *testing.T) {
name := NewBPFObjName("more_than_16_characters_long")
if name[len(name)-1] != 0 {
t.Error("NewBPFObjName doesn't null terminate")
}
if len(name) != unix.BPF_OBJ_NAME_LEN {
t.Errorf("Name is %d instead of %d bytes long", len(name), unix.BPF_OBJ_NAME_LEN)
}
}
26 changes: 13 additions & 13 deletions map.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,25 +317,25 @@ func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *hand
}
}

attr := bpfMapCreateAttr{
mapType: spec.Type,
keySize: spec.KeySize,
valueSize: spec.ValueSize,
maxEntries: spec.MaxEntries,
flags: spec.Flags,
numaNode: spec.NumaNode,
attr := internal.BPFMapCreateAttr{
MapType: uint32(spec.Type),
KeySize: spec.KeySize,
ValueSize: spec.ValueSize,
MaxEntries: spec.MaxEntries,
Flags: spec.Flags,
NumaNode: spec.NumaNode,
}

if inner != nil {
var err error
attr.innerMapFd, err = inner.Value()
attr.InnerMapFd, err = inner.Value()
if err != nil {
return nil, fmt.Errorf("map create: %w", err)
}
}

if haveObjName() == nil {
attr.mapName = newBPFObjName(spec.Name)
attr.MapName = internal.NewBPFObjName(spec.Name)
}

var btfDisabled bool
Expand All @@ -347,13 +347,13 @@ func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *hand
}

if handle != nil {
attr.btfFd = uint32(handle.FD())
attr.btfKeyTypeID = btf.MapKey(spec.BTF).ID()
attr.btfValueTypeID = btf.MapValue(spec.BTF).ID()
attr.BTFFd = uint32(handle.FD())
attr.BTFKeyTypeID = uint32(btf.MapKey(spec.BTF).ID())
attr.BTFValueTypeID = uint32(btf.MapValue(spec.BTF).ID())
}
}

fd, err := bpfMapCreate(&attr)
fd, err := internal.BPFMapCreate(&attr)
if err != nil {
if errors.Is(err, unix.EPERM) {
return nil, fmt.Errorf("map create: RLIMIT_MEMLOCK may be too low: %w", err)
Expand Down
2 changes: 1 addition & 1 deletion prog.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand
}

if haveObjName() == nil {
attr.progName = newBPFObjName(spec.Name)
attr.progName = internal.NewBPFObjName(spec.Name)
}

var err error
Expand Down
119 changes: 42 additions & 77 deletions syscalls.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,6 @@ import (
// Generic errors returned by BPF syscalls.
var ErrNotExist = errors.New("requested object does not exist")

// bpfObjName is a null-terminated string made up of
// 'A-Za-z0-9_' characters.
type bpfObjName [unix.BPF_OBJ_NAME_LEN]byte

// newBPFObjName truncates the result if it is too long.
func newBPFObjName(name string) bpfObjName {
var result bpfObjName
copy(result[:unix.BPF_OBJ_NAME_LEN-1], name)
return result
}

// invalidBPFObjNameChar returns true if char may not appear in
// a BPF object name.
func invalidBPFObjNameChar(char rune) bool {
Expand All @@ -45,21 +34,6 @@ func invalidBPFObjNameChar(char rune) bool {
}
}

type bpfMapCreateAttr struct {
mapType MapType
keySize uint32
valueSize uint32
maxEntries uint32
flags uint32
innerMapFd uint32 // since 4.12 56f668dfe00d
numaNode uint32 // since 4.14 96eabe7a40aa
mapName bpfObjName // since 4.15 ad5b177bd73f
mapIfIndex uint32
btfFd uint32
btfKeyTypeID btf.TypeID
btfValueTypeID btf.TypeID
}

type bpfMapOpAttr struct {
mapFd uint32
padding uint32
Expand All @@ -86,10 +60,10 @@ type bpfMapInfo struct {
value_size uint32
max_entries uint32
map_flags uint32
name bpfObjName // since 4.15 ad5b177bd73f
ifindex uint32 // since 4.16 52775b33bb50
btf_vmlinux_value_type_id uint32 // since 5.6 85d33df357b6
netns_dev uint64 // since 4.16 52775b33bb50
name internal.BPFObjName // since 4.15 ad5b177bd73f
ifindex uint32 // since 4.16 52775b33bb50
btf_vmlinux_value_type_id uint32 // since 5.6 85d33df357b6
netns_dev uint64 // since 4.16 52775b33bb50
netns_ino uint64
btf_id uint32 // since 4.18 78958fca7ead
btf_key_type_id uint32 // since 4.18 9b2cf328b2ec
Expand All @@ -104,11 +78,11 @@ type bpfProgLoadAttr struct {
logLevel uint32
logSize uint32
logBuf internal.Pointer
kernelVersion uint32 // since 4.1 2541517c32be
progFlags uint32 // since 4.11 e07b98d9bffe
progName bpfObjName // since 4.15 067cae47771c
progIfIndex uint32 // since 4.15 1f6f4cb7ba21
expectedAttachType AttachType // since 4.17 5e43f899b03a
kernelVersion uint32 // since 4.1 2541517c32be
progFlags uint32 // since 4.11 e07b98d9bffe
progName internal.BPFObjName // since 4.15 067cae47771c
progIfIndex uint32 // since 4.15 1f6f4cb7ba21
expectedAttachType AttachType // since 4.17 5e43f899b03a
progBTFFd uint32
funcInfoRecSize uint32
funcInfo internal.Pointer
Expand All @@ -132,7 +106,7 @@ type bpfProgInfo struct {
created_by_uid uint32
nr_map_ids uint32
map_ids internal.Pointer
name bpfObjName // since 4.15 067cae47771c
name internal.BPFObjName // since 4.15 067cae47771c
ifindex uint32
gpl_compatible uint32
netns_dev uint64
Expand Down Expand Up @@ -205,23 +179,14 @@ func bpfProgTestRun(attr *bpfProgTestRunAttr) error {
return err
}

func bpfMapCreate(attr *bpfMapCreateAttr) (*internal.FD, error) {
fd, err := internal.BPF(internal.BPF_MAP_CREATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
if err != nil {
return nil, err
}

return internal.NewFD(uint32(fd)), nil
}

var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() error {
_, err := bpfMapCreate(&bpfMapCreateAttr{
mapType: ArrayOfMaps,
keySize: 4,
valueSize: 4,
maxEntries: 1,
_, err := internal.BPFMapCreate(&internal.BPFMapCreateAttr{
MapType: uint32(ArrayOfMaps),
KeySize: 4,
ValueSize: 4,
MaxEntries: 1,
// Invalid file descriptor.
innerMapFd: ^uint32(0),
InnerMapFd: ^uint32(0),
})
if errors.Is(err, unix.EINVAL) {
return internal.ErrNotSupported
Expand All @@ -235,12 +200,12 @@ var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() error {
var haveMapMutabilityModifiers = internal.FeatureTest("read- and write-only maps", "5.2", func() error {
// This checks BPF_F_RDONLY_PROG and BPF_F_WRONLY_PROG. Since
// BPF_MAP_FREEZE appeared in 5.2 as well we don't do a separate check.
m, err := bpfMapCreate(&bpfMapCreateAttr{
mapType: Array,
keySize: 4,
valueSize: 4,
maxEntries: 1,
flags: unix.BPF_F_RDONLY_PROG,
m, err := internal.BPFMapCreate(&internal.BPFMapCreateAttr{
MapType: uint32(Array),
KeySize: 4,
ValueSize: 4,
MaxEntries: 1,
Flags: unix.BPF_F_RDONLY_PROG,
})
if err != nil {
return internal.ErrNotSupported
Expand Down Expand Up @@ -417,15 +382,15 @@ func bpfGetMapInfoByFD(fd *internal.FD) (*bpfMapInfo, error) {
}

var haveObjName = internal.FeatureTest("object names", "4.15", func() error {
attr := bpfMapCreateAttr{
mapType: Array,
keySize: 4,
valueSize: 4,
maxEntries: 1,
mapName: newBPFObjName("feature_test"),
attr := internal.BPFMapCreateAttr{
MapType: uint32(Array),
KeySize: 4,
ValueSize: 4,
MaxEntries: 1,
MapName: internal.NewBPFObjName("feature_test"),
}

fd, err := bpfMapCreate(&attr)
fd, err := internal.BPFMapCreate(&attr)
if err != nil {
return internal.ErrNotSupported
}
Expand All @@ -439,15 +404,15 @@ var objNameAllowsDot = internal.FeatureTest("dot in object names", "5.2", func()
return err
}

attr := bpfMapCreateAttr{
mapType: Array,
keySize: 4,
valueSize: 4,
maxEntries: 1,
mapName: newBPFObjName(".test"),
attr := internal.BPFMapCreateAttr{
MapType: uint32(Array),
KeySize: 4,
ValueSize: 4,
MaxEntries: 1,
MapName: internal.NewBPFObjName(".test"),
}

fd, err := bpfMapCreate(&attr)
fd, err := internal.BPFMapCreate(&attr)
if err != nil {
return internal.ErrNotSupported
}
Expand All @@ -458,14 +423,14 @@ var objNameAllowsDot = internal.FeatureTest("dot in object names", "5.2", func()

var haveBatchAPI = internal.FeatureTest("map batch api", "5.6", func() error {
var maxEntries uint32 = 2
attr := bpfMapCreateAttr{
mapType: Hash,
keySize: 4,
valueSize: 4,
maxEntries: maxEntries,
attr := internal.BPFMapCreateAttr{
MapType: uint32(Hash),
KeySize: 4,
ValueSize: 4,
MaxEntries: maxEntries,
}

fd, err := bpfMapCreate(&attr)
fd, err := internal.BPFMapCreate(&attr)
if err != nil {
return internal.ErrNotSupported
}
Expand Down
11 changes: 0 additions & 11 deletions syscalls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"testing"

"github.com/cilium/ebpf/internal/testutils"
"github.com/cilium/ebpf/internal/unix"
)

func TestObjNameCharacters(t *testing.T) {
Expand All @@ -24,16 +23,6 @@ func TestObjNameCharacters(t *testing.T) {
}
}

func TestObjName(t *testing.T) {
name := newBPFObjName("more_than_16_characters_long")
if name[len(name)-1] != 0 {
t.Error("newBPFObjName doesn't null terminate")
}
if len(name) != unix.BPF_OBJ_NAME_LEN {
t.Errorf("Name is %d instead of %d bytes long", len(name), unix.BPF_OBJ_NAME_LEN)
}
}

func TestHaveBatchAPI(t *testing.T) {
testutils.CheckFeatureTest(t, haveBatchAPI)
}
Expand Down