Skip to content

Commit

Permalink
rename *ABI to MapInfo, ProgramInfo
Browse files Browse the repository at this point in the history
MapInfo and ProgramInfo are now what people expect them to be: metadata
about maps and programs. Depending on the kernel there will be different
kinds of metadata available.

Fixes #33
  • Loading branch information
lmb committed Nov 20, 2020
1 parent 9833efb commit 135a4ab
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 216 deletions.
117 changes: 33 additions & 84 deletions info.go
Expand Up @@ -2,46 +2,35 @@ package ebpf

import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"os"
"strings"
"syscall"

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

// MapABI are the attributes of a Map which are available across all supported kernels.
type MapABI struct {
// MapInfo describes a map.
type MapInfo struct {
Type MapType
KeySize uint32
ValueSize uint32
MaxEntries uint32
Flags uint32
}

func newMapABIFromSpec(spec *MapSpec) *MapABI {
return &MapABI{
spec.Type,
spec.KeySize,
spec.ValueSize,
spec.MaxEntries,
spec.Flags,
}
}

func newMapABIFromFd(fd *internal.FD) (string, *MapABI, error) {
func newMapInfoFromFd(fd *internal.FD) (*MapInfo, error) {
info, err := bpfGetMapInfoByFD(fd)
if errors.Is(err, syscall.EINVAL) {
return newMapInfoFromProc(fd)
}
if err != nil {
if errors.Is(err, syscall.EINVAL) {
abi, err := newMapABIFromProc(fd)
return "", abi, err
}
return "", nil, err
return nil, err
}

return "", &MapABI{
return &MapInfo{
MapType(info.map_type),
info.key_size,
info.value_size,
Expand All @@ -50,87 +39,57 @@ func newMapABIFromFd(fd *internal.FD) (string, *MapABI, error) {
}, nil
}

func newMapABIFromProc(fd *internal.FD) (*MapABI, error) {
var abi MapABI
func newMapInfoFromProc(fd *internal.FD) (*MapInfo, error) {
var mi MapInfo
err := scanFdInfo(fd, map[string]interface{}{
"map_type": &abi.Type,
"key_size": &abi.KeySize,
"value_size": &abi.ValueSize,
"max_entries": &abi.MaxEntries,
"map_flags": &abi.Flags,
"map_type": &mi.Type,
"key_size": &mi.KeySize,
"value_size": &mi.ValueSize,
"max_entries": &mi.MaxEntries,
"map_flags": &mi.Flags,
})
if err != nil {
return nil, err
}
return &abi, nil
return &mi, nil
}

// Equal returns true if two ABIs have the same values.
func (abi *MapABI) Equal(other *MapABI) bool {
switch {
case abi.Type != other.Type:
return false
case abi.KeySize != other.KeySize:
return false
case abi.ValueSize != other.ValueSize:
return false
case abi.MaxEntries != other.MaxEntries:
return false
case abi.Flags != other.Flags:
return false
default:
return true
}
}

// ProgramABI are the attributes of a Program which are available across all supported kernels.
type ProgramABI struct {
// ProgramInfo describes a program.
type ProgramInfo struct {
Type ProgramType
}

func newProgramABIFromFd(fd *internal.FD) (string, *ProgramABI, error) {
func newProgramInfoFromFd(fd *internal.FD) (*ProgramInfo, error) {
info, err := bpfGetProgInfoByFD(fd)
if err != nil {
if errors.Is(err, syscall.EINVAL) {
return newProgramABIFromProc(fd)
}

return "", nil, err
if errors.Is(err, syscall.EINVAL) {
return newProgramInfoFromProc(fd)
}

var name string
if bpfName := internal.CString(info.name[:]); bpfName != "" {
name = bpfName
} else {
name = internal.CString(info.tag[:])
if err != nil {
return nil, err
}

return name, &ProgramABI{
Type: ProgramType(info.prog_type),
return &ProgramInfo{
ProgramType(info.prog_type),
}, nil
}

func newProgramABIFromProc(fd *internal.FD) (string, *ProgramABI, error) {
var (
abi ProgramABI
name string
)
func newProgramInfoFromProc(fd *internal.FD) (*ProgramInfo, error) {
var info ProgramInfo

err := scanFdInfo(fd, map[string]interface{}{
"prog_type": &abi.Type,
"prog_tag": &name,
"prog_type": &info.Type,
})
if errors.Is(err, errMissingFields) {
return "", nil, &internal.UnsupportedFeatureError{
Name: "reading ABI from /proc/self/fdinfo",
return nil, &internal.UnsupportedFeatureError{
Name: "reading program info from /proc/self/fdinfo",
MinimumVersion: internal.Version{4, 10, 0},
}
}
if err != nil {
return "", nil, err
return nil, err
}

return name, &abi, nil
return &info, nil
}

func scanFdInfo(fd *internal.FD, fields map[string]interface{}) error {
Expand Down Expand Up @@ -188,13 +147,3 @@ func scanFdInfoReader(r io.Reader, fields map[string]interface{}) error {

return nil
}

// Equal returns true if two ABIs have the same values.
func (abi *ProgramABI) Equal(other *ProgramABI) bool {
switch {
case abi.Type != other.Type:
return false
default:
return true
}
}
77 changes: 35 additions & 42 deletions info_test.go
Expand Up @@ -3,28 +3,11 @@ package ebpf
import (
"testing"

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

func TestMapABIEqual(t *testing.T) {
abi := &MapABI{
Type: Array,
KeySize: 4,
ValueSize: 2,
MaxEntries: 3,
Flags: 1,
}

if !abi.Equal(abi) {
t.Error("Equal returns true when comparing an ABI to itself")
}

if abi.Equal(&MapABI{}) {
t.Error("Equal returns true for different ABIs")
}
}

func TestMapABIFromProc(t *testing.T) {
func TestMapInfoFromProc(t *testing.T) {
hash, err := NewMap(&MapSpec{
Type: Hash,
KeySize: 4,
Expand All @@ -37,29 +20,29 @@ func TestMapABIFromProc(t *testing.T) {
}
defer hash.Close()

abi, err := newMapABIFromProc(hash.fd)
info, err := newMapInfoFromProc(hash.fd)
if err != nil {
t.Fatal("Can't get map ABI:", err)
t.Fatal("Can't get map info:", err)
}

if abi.Type != Hash {
t.Error("Expected Hash, got", abi.Type)
if info.Type != Hash {
t.Error("Expected Hash, got", info.Type)
}

if abi.KeySize != 4 {
t.Error("Expected KeySize of 4, got", abi.KeySize)
if info.KeySize != 4 {
t.Error("Expected KeySize of 4, got", info.KeySize)
}

if abi.ValueSize != 5 {
t.Error("Expected ValueSize of 5, got", abi.ValueSize)
if info.ValueSize != 5 {
t.Error("Expected ValueSize of 5, got", info.ValueSize)
}

if abi.MaxEntries != 2 {
t.Error("Expected MaxEntries of 2, got", abi.MaxEntries)
if info.MaxEntries != 2 {
t.Error("Expected MaxEntries of 2, got", info.MaxEntries)
}

if abi.Flags != 1 {
t.Error("Expected Flags to be 1, got", abi.Flags)
if info.Flags != 1 {
t.Error("Expected Flags to be 1, got", info.Flags)
}

nested, err := NewMap(&MapSpec{
Expand All @@ -79,20 +62,30 @@ func TestMapABIFromProc(t *testing.T) {
}
defer nested.Close()

_, err = newMapABIFromProc(nested.fd)
_, err = newMapInfoFromProc(nested.fd)
if err != nil {
t.Fatal("Can't get nested map ABI from /proc:", err)
t.Fatal("Can't get nested map info from /proc:", err)
}
}

func TestProgramABI(t *testing.T) {
abi := &ProgramABI{Type: SocketFilter}

if !abi.Equal(abi) {
t.Error("Equal returns true when comparing an ABI to itself")
}

if abi.Equal(&ProgramABI{}) {
t.Error("Equal returns true for different ABIs")
func TestProgramInfo(t *testing.T) {
prog := createSocketFilter(t)
defer prog.Close()

for name, fn := range map[string]func(*internal.FD) (*ProgramInfo, error){
"generic": newProgramInfoFromFd,
"proc": newProgramInfoFromProc,
} {
t.Run(name, func(t *testing.T) {
info, err := fn(prog.fd)
testutils.SkipIfNotSupported(t, err)
if err != nil {
t.Fatal("Can't get program info:", err)
}

if info.Type != SocketFilter {
t.Error("Expected Type to be SocketFilter, got", info.Type)
}
})
}
}

0 comments on commit 135a4ab

Please sign in to comment.