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 的映射:一个是根据 bpftool
的 bpf_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。
希望对您有所帮助!
这是
所以,在我看来,必须有一个 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 的映射:一个是根据 bpftool
的 bpf_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。
希望对您有所帮助!