BPF:地图的所有者

BPF: owner of a map

这是 的后续问题,因为我的新问题与那个话题没有直接关系。

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

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

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

所以这意味着用户程序,例如 bpftool,将开始创建在 bpf ELF 部分中找到的映射,如 线程中所示。

另一方面,用户应用程序需要 add/delete 映射中的条目。为此,它必须知道 map 的 ID,以便从 libbpf 获得带有 bpf_map_get_fd_by_id() 的 get map 的 fd。之后我们可以享受 bpf_map_update_elem() 和类似的 APIs.

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

所以在这种情况下,我们将有两个具有两个不同 ID 的映射:一个是根据 bpftoolbpf_prog_load() 创建的,另一个是用户应用程序的 [=18] =](假设应用程序继续 运行,例如更新地图,而不是 return 到 shell)。

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

我不太确定我理解你的问题,让我试着重新表述一下。

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

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

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

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

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

地图 ID 是最近添加的,主要用于调试或自省,但它们可能提供另一种方法来检索地图的文件描述符,如您在 bpf_map_get_fd_by_id() 中描述的那样。虽然你得先想办法拿到ID。

希望对您有所帮助!