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

Simplify GetMapsIDsByName #384

Merged
merged 8 commits into from
Oct 23, 2023
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
62 changes: 47 additions & 15 deletions map-low.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package libbpfgo
import "C"

import (
"errors"
"fmt"
"syscall"
"unsafe"
Expand Down Expand Up @@ -99,29 +100,60 @@ 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{}
// GetMapNextID retrieves the next available map ID after the given startID.
// It returns the next map ID and an error if one occurs during the operation.
func GetMapNextID(startId uint32) (uint32, error) {
startIDC := C.uint(startId)
retC := C.bpf_map_get_next_id(startIDC, &startIDC)
if retC == 0 {
return uint32(startIDC), nil
}

return uint32(startIDC), fmt.Errorf("failed to get next map id: %w", syscall.Errno(-retC))
}

startId := C.uint(0)
nextId := C.uint(0)
// GetMapsIDsByName searches for maps with a specified name and collects their IDs.
// It starts the search from the given 'startId' and continues until no more matching maps are found.
// The function returns a slice of unsigned 32-bit integers representing the IDs of matching maps.
// If no maps with the provided 'name' are found, it returns an empty slice and no error.
// The 'startId' is modified and returned as the last processed map ID.
//
// Example Usage:
//
// name := "myMap" // The name of the map you want to find.
// startId := uint32(0) // The map ID to start the search from.
//
// var mapIDs []uint32 // Initialize an empty slice to collect map IDs.
// var err error // Initialize an error variable.
//
// // Retry mechanism in case of errors using the last processed 'startId'.
// for {
// mapIDs, err = GetMapsIDsByName(name, startId)
// if err != nil {
// // Handle other errors, possibly with a retry mechanism.
// // You can use the 'startId' who contains the last processed map ID to continue the search.
aymericDD marked this conversation as resolved.
Show resolved Hide resolved
// } else {
// // Successful search, use the 'mapIDs' slice containing the IDs of matching maps.
// // Update 'startId' to the last processed map ID to continue the search.
// }
// }
func GetMapsIDsByName(name string, startId *uint32) ([]uint32, error) {
var (
bpfMapsIds []uint32
err error
)

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

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

startId = nextId + 1

bpfMapLow, err := GetMapByID(uint32(nextId))
bpfMapLow, err := GetMapByID(*startId)
if err != nil {
return bpfMapsIds, err
}
Expand Down
11 changes: 11 additions & 0 deletions selftest/map-getmapsbyname/main.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,15 @@ struct {
__uint(value_size, sizeof(u32));
} test_name SEC(".maps");

struct test_struct {
char value[10];
};

struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 1);
__type(key, int);
__type(value, struct test_struct);
} test_hash_name SEC(".maps");

char LICENSE[] SEC("license") = "Dual BSD/GPL";
16 changes: 14 additions & 2 deletions selftest/map-getmapsbyname/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
const (
BPFMapNameToNotFind = "not_found"
// The following properties are used to identify the map
BPFHashMapNameToFind = "test_hash_name"
BPFMapNameToFind = "test_name"
BPFMapTypeToFind = bpf.MapTypeArray
BPFMapMaxEntriesToFind = 1
Expand All @@ -29,12 +30,23 @@ func main() {

bpfModule.BPFLoadObject()

notFoundMapsIDs, err := bpf.GetMapsIDsByName(BPFMapNameToNotFind)
startId := uint32(0)
notFoundMapsIDs, err := bpf.GetMapsIDsByName(BPFMapNameToNotFind, &startId)
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)
startId = 0
bpfHashMapsIDs, err := bpf.GetMapsIDsByName(BPFHashMapNameToFind, &startId)
if err != nil {
log.Fatal(err)
}
if len(bpfHashMapsIDs) == 0 {
log.Fatalf("the %s map should be found", BPFHashMapNameToFind)
}

startId = 0
mapsIDs, err := bpf.GetMapsIDsByName(BPFMapNameToFind, &startId)
if err != nil {
log.Fatal(err)
}
Expand Down