5

这是谁在 BPF 中创建地图的后续行动,因为我的新问题与该线程没有直接关系。

所以,在我看来,必须有一个创建 BPF 映射的,要么是 bpf 程序,要么是加载 bpf 的用户程序等。

BPF 程序必须在编译时知道它将使用的映射类型,所以我们需要:

struct bpf_map_def SEC("maps") my_map = {
...
};

所以这意味着一个用户程序,例如bpftool,将启动在 bpf ELF 部分中找到的映射的创建,如谁在 BPF线程中创建映射所示。

另一方面,用户应用程序将需要在地图中添加/删除条目。为此,它必须知道 mapID才能使用bpf_map_get_fd_by_id()from获取 get map 的 fd libbpf。之后我们就可以享受bpf_map_update_elem()和类似的API了。

另一方面,如果我们在 BPF 程序中声明了一个 map 部分并且确实使用了 map API,则 map(s) 将保留在内核中并分配 ID。

所以在这种情况下,我们将有两个具有两个不同 ID 的映射:一个作为bpf_prog_load()from的结果创建bpftool,另一个来自用户应用程序bpf_create_map()(假设应用程序继续运行,例如更新映射,并且不返回到 shell )。

一定有办法绕过这种歧义吗?

4

1 回答 1

7

我不完全确定我理解你的问题,让我试着改写一下。

  • 使用 加载一个 eBPF 程序bpftool,它会创建程序所需的所有映射。bpftool 一个用户空间应用程序,并最终使用bpf(BPF_MAP_CREATE, …)系统调用创建映射。
  • 您有另一个与这些映射交互的用户空间应用程序foobar,可能通过使用 libbpf(最终执行bpf(BPF_MAP_*, …)系统调用)从映射中查找、更新或删除元素。
  • 据我了解,第二个应用程序foobar 尝试创建地图。bpftool因此,您在创建的地图和创建的地图之间存在冲突foobar

如果这是正确的,则解决方案很“简单”:不要创建两次地图。

这意味着您应该bpf_create_map()从其他应用程序中删除对 的调用foobar,或者使用bpftool. 通常,工作流包括在 eBPF 对象文件中描述的映射,并由加载程序的同一应用程序在加载之前创建——这就是这样bpftool做的。然后应用程序拥有地图的文件描述符并且可以使用它。

或者,可以将映射固定在 BPF 虚拟文件系统 ( /sys/fs/bpf/) 下,以便另一个应用程序可以检索文件描述符并访问此映射。这是通过系统调用完成的bpf(BPF_OBJ_GET, …)(目前尚未在手册页上记录,至少在我的系统上)。

如果我是正确的,使用固定地图还可以允许在加载新的 eBPF 程序时重用已经存在的地图。tc如果所描述的地图存在并且已经固定,我相信从包 iproute2 打算这样做(请参阅文件lib/bpf.c,但代码并不完全易于阅读)。这通常会在重定位时执行。

最近添加了 Maps ID,主要用于调试或自省,但在您的情况下,它们可能会提供另一种方法来将文件描述符检索到地图中,正如您使用bpf_map_get_fd_by_id(). 尽管您必须首先找到一种获取ID的方法。

希望这可以帮助!

于 2018-01-05T23:12:08.020 回答