6

是否可以在不同程序类型之间共享 ebpf 映射。我需要在 tc-bpf 程序和 cgroup bpf 程序之间共享一个映射。如果映射固定到充当全局命名空间的文件系统,这应该是可能的。但是,我还没有这个工作。

该映射由 tc-bpf 程序创建并固定到全局命名空间。由于是 tc-bpf 程序,map 的类型为 struct bpf_elf_map。这个 bpf 程序是通过 iproute2 加载的。

现在,我有一个应该访问此映射的 cgroup bpf 程序,但由于它是通过 user.c (libbpf) 或 bpftool 而不是 iproute 加载的,因此此处定义的映射不能是“bpf_elf_map”,而是结构bpf_map_def。所以在cgroup bpf程序中,同样的map被定义为struct bpf_map_def而不是struct bpf_elf_map。

可能正因为如此,当我转储地图(并且不共享预期的地图)时,cgroup 程序会获得一个新的 map_id,理想情况下,当 bpf 程序共享相同的地图时,这些 bpf 程序将具有与其唯一关联的相同 map_id prog_ids。

4

1 回答 1

5

可以在不同类型的程序之间共享对 eBPF 映射的访问。

struct bpf_elf_map首先,您可以忘记和之间的差异struct bpf_map_def。它们是用户空间中用于构建传递给内核的对象的结构。Iproute2 和 libbpf 可能不使用相同的结构/属性名称,但它们最终都会以bpf()相同的格式将映射元数据传递给系统调用,否则内核将无法理解要创建的映射。

当它们被加载到内核时,eBPF 程序通过文件描述符引用给定的映射到这个映射。这意味着调用bpf()系统调用来加载程序的进程首先必须将文件描述符检索到要使用的映射。所以可能会出现以下两种情况:

  • 用户空间应用程序(ip、tc、bpftool...)解析 ELF 对象文件并收集与地图相关的元数据。它没有识别(甚至可能没有尝试识别)任何应该为程序重用的现有地图。因此它使用系统调用创建一个新映射,该bpf()系统调用将一个文件描述符返回到这个新创建的映射。该文件描述符用于涉及映射访问的程序指令中(一旦程序加载到内核中,这些文件描述符将被映射地址替换),然后使用bpf()系统调用加载程序。这就是您的 tc 程序发生的情况,在您的情况下,您的 cgroup 程序似乎正在创建第二个地图。

  • 或者用户应用程序解析 ELF 目标文件,并以某种方式发现已经存在程序应该使用的映射。例如,它会找到 id 为 1337 的地图,或者在/sys/fs/bpf/. 在这种情况下,它会检索到该映射的文件描述符(从带有bpf()系统调用的 id,从带有 的固定路径open())。然后和第一种情况一样,它使用这个文件描述符来准备然后加载程序。

Libbpf 提供了一种方法来重用给定映射的文件描述符以与程序一起使用。参见例如bpf_map__reuse_fd()。Bpftool使用它来支持重用现有地图,并带有map参数 for bpftool prog load(请参阅参考资料man bpftool-prog)。例如,加载一个程序foo.o并告诉它为27在目标文件中找到的第一个地图重用 id 地图,然后将地图固定在目标文件中/sys/fs/bpf/foomap命名的地图上foomap

# bpftool prog load foo.o /sys/fs/bpf/foo_prog \
        map idx 0 id 27 \
        map foomap stats pinned /sys/fs/bpf/foomap
于 2020-02-14T13:48:40.767 回答