我会创建一个映射来存储一个元素(端口号),它应该从用户空间和内核空间读取/写入。 我应该使用哪种地图类型?键和值的大小合适,如何从两端写入/读取?
_user.c
/* create array map with one element */
map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value), 1, 0);
...
/* update map */
ret = bpf_map_update_elem(map_fd, &key, &i, BPF_ANY);
_kern.c
如何参考map_fd并在同一张地图上操作?
编辑:
我只能以一种方式成功创建地图并与之交互: 在_kern.c
文件中定义映射,如下所示:
struct bpf_map_def SEC("maps") my_map = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(uint32_t),
.value_size = sizeof(uint32_t),
.max_entries = 1,
};
该定义允许使用 bpf 助手(如bpf_map_lookup_elem
)直接在地图上进行操作。
而是在_user.c
内通过我使用的bpf_prog_load
将_kern.o
ebpf 程序加载到内核中
map_fd = bpf_object__find_map_fd_by_name(obj, "my_map");
检索与地图关联的文件描述符(我错过了这一点)。获得文件描述符后,例如,您可以调用地图更新
ret = bpf_map_update_elem(map_fd, &key, &value, BPF_ANY);
问题:在这种情况下,我使用 libbpf 从用户空间检索 fd,但是如果我使用bpf_create_map
从_user.c
创建映射,那么如何从 ebpf 程序中检索 fd?
如果你知道你只有一个元素,最简单的方法可能是去找一个数组映射。在这种情况下,您可以通过数组中的索引轻松访问映射条目:0
。
如果你要这样做,键的大小将是 4 字节整数 (sizeof(uint32_t)
的大小,它总是用于数组索引。该值的大小将是存储端口号所需的大小:很可能是sizeof(uint16_t)
。
然后,您可以通过调用相关的 BPF 帮助程序函数从 BPF 程序读取/写入:bpf_map_lookup_elem()
或bpf_map_update_elem()
(有关详细信息,请参阅手册页)。它们通常以通常不安装在系统上的bpf_helpers.h
中定义,您可以在 bcc 或内核存储库中找到它的版本。
在用户空间中,您可以使用bpf()
系统调用及其相关命令更新条目:BPF_MAP_LOOKUP_ELEM()
和BPF_MAP_UPDATE_ELEM()
(参见手册页)。但是你不一定要自己重新实现调用:如果你编写一个程序,你可能应该看看提供包装器的libbpf。如果要从命令行更新映射,这很容易使用bpftool
(参见手册页)、bpftool map <map_ref> update key 0 0 0 0 value 0x37 0x13
(更新)或bpftool map <map_ref> lookup key 0 0 0 0
(查找)等