eBPF映射一个元素。映射类型和内核/用户空间通信

时间:2019-08-23 14:38:27

标签: c kernel ebpf

我将创建一个仅存储一个元素(端口号)的映射,并且应该同时从用户空间和内核空间对其进行读写。 我应该使用哪种地图类型?哪种键和值大小合适?我该如何从双方进行写/读?

_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_map_lookup_elem之类的bpf帮助程序直接在地图上进行操作。

通过_user.c_kern.o ebpf程序加载到内核之后,在bpf_prog_load

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,但是如果我使用_user.cbpf_create_map创建映射,那么如何检索fd来自ebpf程序?

1 个答案:

答案 0 :(得分:2)

如果您知道只有一个元素,那么最简单的方法可能就是使用数组映射。在这种情况下,您可以通过其在数组0中的索引来轻松访问地图条目。

如果要这样做,键的大小将是4字节整数(sizeof(uint32_t))的大小,该整数始终用于数组索引。值的大小就是您存储端口号所需的大小:很可能是sizeof(uint16_t)

然后,您可以通过调用相关的BPF帮助器函数:bpf_map_lookup_elem()bpf_map_update_elem()(有关详细信息,请参见man page)来从BPF程序中读取/写入。它们通常在bpf_helpers.h中定义,通常不会安装在系统上,您可以在密件抄送或内核存储库中找到其版本。

在用户空间中,您将使用bpf()系统调用及其相关命令:BPF_MAP_LOOKUP_ELEM()BPF_MAP_UPDATE_ELEM()(请参阅man page)来更新条目。但是您不必一定要自己重新实现调用:如果编写程序,则可能应该看看提供包装程序的libbpf。如果您想从命令行更新地图,可以使用bpftool(请参见man page)来完成,例如bpftool map <map_ref> update key 0 0 0 0 value 0x37 0x13(更新)或bpftool map <map_ref> lookup key 0 0 0 0(查找) )。