Skip to content

Commit e6e4387

Browse files
aymericDDgeyslan
andcommitted
feat(map): Introduce GetMapsIDsByName
Allow a user to get a list of maps IDs filtered by map name. Co-authored-by: Geyslan Gregório <geyslan@gmail.com>
1 parent c11365c commit e6e4387

File tree

7 files changed

+150
-0
lines changed

7 files changed

+150
-0
lines changed

map-low.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,45 @@ func GetMapByID(id uint32) (*BPFMapLow, error) {
9999
}, nil
100100
}
101101

102+
// GetMapsIDsByName searches for maps with a given name.
103+
// It returns a slice of unsigned 32-bit integers representing the IDs of matching maps.
104+
// If no maps are found, it returns an empty slice and no error.
105+
func GetMapsIDsByName(name string) ([]uint32, error) {
106+
bpfMapsIds := []uint32{}
107+
108+
startId := C.uint(0)
109+
nextId := C.uint(0)
110+
111+
for {
112+
retC := C.bpf_map_get_next_id(startId, &nextId)
113+
errno := syscall.Errno(-retC)
114+
if retC < 0 {
115+
if errno == syscall.ENOENT {
116+
return bpfMapsIds, nil
117+
}
118+
119+
return bpfMapsIds, fmt.Errorf("failed to get next map id: %w", errno)
120+
}
121+
122+
startId = nextId + 1
123+
124+
bpfMapLow, err := GetMapByID(uint32(nextId))
125+
if err != nil {
126+
return bpfMapsIds, err
127+
}
128+
129+
if err := syscall.Close(bpfMapLow.FileDescriptor()); err != nil {
130+
return bpfMapsIds, err
131+
}
132+
133+
if bpfMapLow.Name() != name {
134+
continue
135+
}
136+
137+
bpfMapsIds = append(bpfMapsIds, bpfMapLow.info.ID)
138+
}
139+
}
140+
102141
//
103142
// BPFMapLow Specs
104143
//
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../common/Makefile

selftest/map-getmapsbyname/go.mod

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module github.com/aquasecurity/libbpfgo/selftest/map-update
2+
3+
go 1.18
4+
5+
require github.com/aquasecurity/libbpfgo v0.4.7-libbpf-1.2.0-b2e29a1
6+
7+
replace github.com/aquasecurity/libbpfgo => ../../

selftest/map-getmapsbyname/go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
3+
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
4+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//+build ignore
2+
3+
#include <vmlinux.h>
4+
5+
#include <bpf/bpf_helpers.h>
6+
7+
struct {
8+
__uint(type, BPF_MAP_TYPE_ARRAY);
9+
__uint(max_entries, 1);
10+
__uint(key_size, sizeof(u32));
11+
__uint(value_size, sizeof(u32));
12+
} test_name SEC(".maps");
13+
14+
char LICENSE[] SEC("license") = "Dual BSD/GPL";

selftest/map-getmapsbyname/main.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package main
2+
3+
import "C"
4+
5+
import (
6+
"log"
7+
"syscall"
8+
"unsafe"
9+
10+
bpf "github.com/aquasecurity/libbpfgo"
11+
)
12+
13+
const (
14+
BPFMapNameToNotFind = "not_found"
15+
// The following properties are used to identify the map
16+
BPFMapNameToFind = "test_name"
17+
BPFMapTypeToFind = bpf.MapTypeArray
18+
BPFMapMaxEntriesToFind = 1
19+
BPFMapKeySizeToFind = 4
20+
BPFMapValSizeToFind = 4
21+
)
22+
23+
func main() {
24+
bpfModule, err := bpf.NewModuleFromFile("main.bpf.o")
25+
if err != nil {
26+
log.Fatal(err)
27+
}
28+
defer bpfModule.Close()
29+
30+
bpfModule.BPFLoadObject()
31+
32+
notFoundMapsIDs, err := bpf.GetMapsIDsByName(BPFMapNameToNotFind)
33+
if len(notFoundMapsIDs) != 0 {
34+
log.Fatalf("the %s map should not be found, but it was found with ids: %v", BPFMapNameToNotFind, notFoundMapsIDs)
35+
}
36+
37+
mapsIDs, err := bpf.GetMapsIDsByName(BPFMapNameToFind)
38+
if err != nil {
39+
log.Fatal(err)
40+
}
41+
if len(mapsIDs) == 0 {
42+
log.Fatalf("the %s map was not found", BPFMapNameToFind)
43+
}
44+
45+
// try to identify the map by its properties
46+
similarMaps := []*bpf.BPFMapLow{}
47+
for _, id := range mapsIDs {
48+
bpfMap, err := bpf.GetMapByID(id)
49+
if err != nil {
50+
log.Fatalf("the %s map with %d id was not found: %v", BPFMapNameToFind, id, err)
51+
}
52+
53+
if bpfMap.Type() == BPFMapTypeToFind &&
54+
bpfMap.MaxEntries() == BPFMapMaxEntriesToFind &&
55+
bpfMap.KeySize() == BPFMapKeySizeToFind &&
56+
bpfMap.ValueSize() == BPFMapValSizeToFind {
57+
// found a map with the same properties
58+
similarMaps = append(similarMaps, bpfMap)
59+
} else {
60+
if err := syscall.Close(bpfMap.FileDescriptor()); err != nil {
61+
log.Fatalf("failed to close the file descriptor of the %s map with %d id: %v", BPFMapNameToFind, id, err)
62+
}
63+
}
64+
}
65+
66+
if len(similarMaps) == 0 {
67+
log.Fatalf("no %s maps with the same properties found", BPFMapNameToFind)
68+
}
69+
if len(similarMaps) > 1 {
70+
// This is a conundrum for the user, as they cannot decide which map to use
71+
// automatically. Perhaps they should change the name of the map to make it
72+
// unique.
73+
_ = 0
74+
}
75+
76+
// use the first map of the similar ones
77+
bpfMap := similarMaps[0]
78+
79+
key1 := uint32(0)
80+
value1 := uint32(55)
81+
if err := bpfMap.Update(unsafe.Pointer(&key1), unsafe.Pointer(&value1)); err != nil {
82+
log.Fatal(err)
83+
}
84+
}

selftest/map-getmapsbyname/run.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../common/run.sh

0 commit comments

Comments
 (0)