95 lines
2.2 KiB
Go
95 lines
2.2 KiB
Go
|
package ebpf
|
||
|
|
||
|
/*
|
||
|
#include <stdlib.h>
|
||
|
#include <stdint.h>
|
||
|
#include <unistd.h>
|
||
|
#include <linux/unistd.h>
|
||
|
#include <linux/bpf.h>
|
||
|
|
||
|
// See the bpf man page for details on the following functions
|
||
|
|
||
|
static int bpf(enum bpf_cmd cmd, union bpf_attr *attr, unsigned int size)
|
||
|
{
|
||
|
return syscall(__NR_bpf, cmd, attr, size);
|
||
|
}
|
||
|
|
||
|
static int bpf_create_map(
|
||
|
enum bpf_map_type map_type, unsigned int key_size, unsigned int value_size,
|
||
|
unsigned int max_entries)
|
||
|
{
|
||
|
union bpf_attr attr = {
|
||
|
.map_type = map_type,
|
||
|
.key_size = key_size,
|
||
|
.value_size = value_size,
|
||
|
.max_entries = max_entries};
|
||
|
|
||
|
return bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
|
||
|
}
|
||
|
|
||
|
int bpf_get_next_key(int fd, const void *key, void *next_key)
|
||
|
{
|
||
|
union bpf_attr attr = {
|
||
|
.map_fd = fd,
|
||
|
.key = (__u64) (unsigned long) key,
|
||
|
.next_key = (__u64) (unsigned long) next_key};
|
||
|
|
||
|
return bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
|
||
|
}
|
||
|
|
||
|
|
||
|
int bpf_lookup_elem(int fd, const void *key, void *value)
|
||
|
{
|
||
|
union bpf_attr attr = {
|
||
|
.map_fd = fd,
|
||
|
.key = (__u64) (unsigned long) key,
|
||
|
.value = (__u64) (unsigned long) value,
|
||
|
};
|
||
|
|
||
|
return bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
|
||
|
}
|
||
|
|
||
|
*/
|
||
|
import "C"
|
||
|
import (
|
||
|
"fmt"
|
||
|
"syscall"
|
||
|
"unsafe"
|
||
|
)
|
||
|
|
||
|
// CreateMap creates an eBPF map from int->uint64. The file descriptor of the
|
||
|
// created map is returned.
|
||
|
func CreateMap() (int, error) {
|
||
|
mapFD := C.bpf_create_map(C.BPF_MAP_TYPE_HASH, 4, 8, 64)
|
||
|
return int(mapFD), nil
|
||
|
}
|
||
|
|
||
|
// GetMap gets the key/value pairs from the specified eBPF map as a Go map
|
||
|
func GetMap(mapFD int) (map[int]uint64, error) {
|
||
|
retMap := make(map[int]uint64)
|
||
|
|
||
|
mapFDC := C.int(mapFD)
|
||
|
keyC := C.int(0)
|
||
|
nextKeyC := C.int(0)
|
||
|
valC := C.uint64_t(0)
|
||
|
|
||
|
for {
|
||
|
r, errno := C.bpf_get_next_key(mapFDC, unsafe.Pointer(&keyC), unsafe.Pointer(&nextKeyC))
|
||
|
if r == -1 {
|
||
|
if errno == syscall.ENOENT {
|
||
|
// The provided key was the last element. We're done iterating.
|
||
|
return retMap, nil
|
||
|
}
|
||
|
return nil, fmt.Errorf("bpf_get_next_key failed with errno %d", errno)
|
||
|
}
|
||
|
|
||
|
r = C.bpf_lookup_elem(mapFDC, unsafe.Pointer(&nextKeyC), unsafe.Pointer(&valC))
|
||
|
if r == -1 {
|
||
|
return nil, fmt.Errorf("bpf_lookup_elem failed")
|
||
|
}
|
||
|
retMap[int(nextKeyC)] = uint64(valC)
|
||
|
|
||
|
keyC = nextKeyC
|
||
|
}
|
||
|
}
|