Skip to content

Commit

Permalink
feat(map): Introduce GetMapsIDsByName
Browse files Browse the repository at this point in the history
Allow a user to get a list of maps IDs filtered by map name.

Co-authored-by: Geyslan Gregório <[email protected]>
  • Loading branch information
aymericDD and geyslan committed Sep 14, 2023
1 parent c11365c commit e6e4387
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 0 deletions.
39 changes: 39 additions & 0 deletions map-low.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,45 @@ func GetMapByID(id uint32) (*BPFMapLow, error) {
}, nil
}

// GetMapsIDsByName searches for maps with a given name.
// It returns a slice of unsigned 32-bit integers representing the IDs of matching maps.
// If no maps are found, it returns an empty slice and no error.
func GetMapsIDsByName(name string) ([]uint32, error) {
bpfMapsIds := []uint32{}

startId := C.uint(0)
nextId := C.uint(0)

for {
retC := C.bpf_map_get_next_id(startId, &nextId)
errno := syscall.Errno(-retC)
if retC < 0 {
if errno == syscall.ENOENT {
return bpfMapsIds, nil
}

return bpfMapsIds, fmt.Errorf("failed to get next map id: %w", errno)
}

startId = nextId + 1

bpfMapLow, err := GetMapByID(uint32(nextId))
if err != nil {
return bpfMapsIds, err
}

if err := syscall.Close(bpfMapLow.FileDescriptor()); err != nil {
return bpfMapsIds, err
}

if bpfMapLow.Name() != name {
continue
}

bpfMapsIds = append(bpfMapsIds, bpfMapLow.info.ID)
}
}

//
// BPFMapLow Specs
//
Expand Down
1 change: 1 addition & 0 deletions selftest/map-getmapsbyname/Makefile
7 changes: 7 additions & 0 deletions selftest/map-getmapsbyname/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module github.com/aquasecurity/libbpfgo/selftest/map-update

go 1.18

require github.com/aquasecurity/libbpfgo v0.4.7-libbpf-1.2.0-b2e29a1

replace github.com/aquasecurity/libbpfgo => ../../
4 changes: 4 additions & 0 deletions selftest/map-getmapsbyname/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
14 changes: 14 additions & 0 deletions selftest/map-getmapsbyname/main.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//+build ignore

#include <vmlinux.h>

#include <bpf/bpf_helpers.h>

struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__uint(key_size, sizeof(u32));
__uint(value_size, sizeof(u32));
} test_name SEC(".maps");

char LICENSE[] SEC("license") = "Dual BSD/GPL";
84 changes: 84 additions & 0 deletions selftest/map-getmapsbyname/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package main

import "C"

import (
"log"
"syscall"
"unsafe"

bpf "github.com/aquasecurity/libbpfgo"
)

const (
BPFMapNameToNotFind = "not_found"
// The following properties are used to identify the map
BPFMapNameToFind = "test_name"
BPFMapTypeToFind = bpf.MapTypeArray
BPFMapMaxEntriesToFind = 1
BPFMapKeySizeToFind = 4
BPFMapValSizeToFind = 4
)

func main() {
bpfModule, err := bpf.NewModuleFromFile("main.bpf.o")
if err != nil {
log.Fatal(err)
}
defer bpfModule.Close()

bpfModule.BPFLoadObject()

notFoundMapsIDs, err := bpf.GetMapsIDsByName(BPFMapNameToNotFind)
if len(notFoundMapsIDs) != 0 {
log.Fatalf("the %s map should not be found, but it was found with ids: %v", BPFMapNameToNotFind, notFoundMapsIDs)
}

mapsIDs, err := bpf.GetMapsIDsByName(BPFMapNameToFind)
if err != nil {
log.Fatal(err)
}
if len(mapsIDs) == 0 {
log.Fatalf("the %s map was not found", BPFMapNameToFind)
}

// try to identify the map by its properties
similarMaps := []*bpf.BPFMapLow{}
for _, id := range mapsIDs {
bpfMap, err := bpf.GetMapByID(id)
if err != nil {
log.Fatalf("the %s map with %d id was not found: %v", BPFMapNameToFind, id, err)
}

if bpfMap.Type() == BPFMapTypeToFind &&
bpfMap.MaxEntries() == BPFMapMaxEntriesToFind &&
bpfMap.KeySize() == BPFMapKeySizeToFind &&
bpfMap.ValueSize() == BPFMapValSizeToFind {
// found a map with the same properties
similarMaps = append(similarMaps, bpfMap)
} else {
if err := syscall.Close(bpfMap.FileDescriptor()); err != nil {
log.Fatalf("failed to close the file descriptor of the %s map with %d id: %v", BPFMapNameToFind, id, err)
}
}
}

if len(similarMaps) == 0 {
log.Fatalf("no %s maps with the same properties found", BPFMapNameToFind)
}
if len(similarMaps) > 1 {
// This is a conundrum for the user, as they cannot decide which map to use
// automatically. Perhaps they should change the name of the map to make it
// unique.
_ = 0
}

// use the first map of the similar ones
bpfMap := similarMaps[0]

key1 := uint32(0)
value1 := uint32(55)
if err := bpfMap.Update(unsafe.Pointer(&key1), unsafe.Pointer(&value1)); err != nil {
log.Fatal(err)
}
}
1 change: 1 addition & 0 deletions selftest/map-getmapsbyname/run.sh

0 comments on commit e6e4387

Please sign in to comment.