前言¶
记录一下如何在 libbpfgo 程序中使用 ebpf map(ebpf map 本身的资料可以参考参考资料)。
ebpf 程序中使用 ebpf map¶
定义 map¶
先看一下定义一个 ebpf map 的方法,比如类型为 BPF_MAP_TYPE_HASH 的 map:
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, u32);
__type(value, struct event_t);
__uint(max_entries, 1024 * 16);
} event_map SEC(".maps");
可以看到主要需要指定 type 、 key 、 value 、 max_entries 这几个字段。
对 map 进行操作¶
在 ebpf 程序中可以通过下面几个常用的辅助函数对 map 对象进行操作:
void bpf_map_lookup_elem(map, void *key. ...) 通过 key 查找对应的 value
event = bpf_map_lookup_elem(&event_map, &pid);
if (!event) { // key 不存在
return 0;
}
void bpf_map_update_elem(map, void *key, ..., __u64 flags) 更新指定 key 的值, flags 参数用于控制更新行为
/* File: include/uapi/linux/bpf.h */
/* flags for BPF_MAP_UPDATE_ELEM command */
#define BPF_ANY 0 /* create new element or update existing */
#define BPF_NOEXIST 1 /* create new element only if it didn't exist */
#define BPF_EXIST 2 /* only update existing element */
bpf_map_update_elem(&event_map, &pid, &event, BPF_ANY);
void bpf_map_delete_elem(map, void *key) 删除指定 key
bpf_map_delete_elem(&event_map, &pid);
完整示例程序详见: https://github.com/mozillazg/hello-libbpfgo/tree/master/08-map-map-type-hash-kernel
pin map¶
pin map 用于将 map 保存到本地文件系统中进行持久化, libbpf 中是会自动保存到 /sys/fs/bpf/<map_name> 路径下。
定义 pin map 的方法只是在普通 map 的基础上加一个 pinning 字段:
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, u32);
__type(value, struct event_t);
__uint(max_entries, 1024 * 16);
__uint(pinning, LIBBPF_PIN_BY_NAME); // <- pin
} event_map SEC(".maps");
完整示例程序详见: https://github.com/mozillazg/hello-libbpfgo/tree/master/11-map-pin
go 程序中使用 ebpf map¶
可以使用 libbpfgo 在 go 程序中操作 ebpf 程序中定义的 ebpf map。
对 map 进行操作¶
先通过 bpfmap, err := bpfModule.GetMap("bpf_map") 拿到定义的 map 对象,然后就可以 做一些常见的操作了:
Update(key, value unsafe.Pointer) error 更新指定 key 的值,使用的 flags 是 BPF_ANY 即 创建新元素或者更新已有的 key:
key := 1
value := 233
keyPtr := unsafe.Pointer(&key)
valuePtr := unsafe.Pointer(&value)
bpfmap.Update(keyPtr, valuePtr)
GetValue(key unsafe.Pointer) ([]byte, error) 获取指定 key 的值,当 key 不存在时会返回 error:
key := 1
keyPtr := unsafe.Pointer(&key)
data, err := bpfmap.GetValue(keyPtr)
DeleteKey(key unsafe.Pointer) error 删除指定 key,当 key 不存在时会返回 error:
key := 1
keyPtr := unsafe.Pointer(&key)
err := bpfmap.DeleteKey(keyPtr)
完整示例程序详见: https://github.com/mozillazg/hello-libbpfgo/tree/master/09-map-map-type-hash-userspace
Comments