Linux kernel 不同ebpf程序类型之间的映射共享

Linux kernel 不同ebpf程序类型之间的映射共享,linux-kernel,elf,bpf,ebpf,iproute,Linux Kernel,Elf,Bpf,Ebpf,Iproute,是否可以在不同的程序类型之间共享ebpf映射。我需要在tc bpf程序和cgroup bpf程序之间共享一个映射。如果映射被固定到充当全局命名空间的文件系统,那么这应该是可能的。但是,我还没有让它工作 该映射由tc bpf程序创建,并固定到全局命名空间。由于它是tc bpf程序,映射类型为struct bpf_elf_map。此bpf程序通过iproute2加载 现在,我有一个cgroup bpf程序,它应该访问这个映射,但是由于它是通过user.c(libbpf)或bpftool加载的,而不是

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

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

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


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

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

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

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

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

  • 或者用户应用程序解析ELF对象文件,并以某种方式发现程序应该使用的现有映射。例如,它会在
    /sys/fs/bpf/
    下查找id为1337的映射,或固定的映射。在这种情况下,它检索到该映射的文件描述符(从带有
    bpf()
    syscall的id,从带有
    open()
    的固定路径)。然后,与第一种情况一样,它使用此文件描述符准备并加载程序

Libbpf提供了一种为给定映射重用文件描述符以用于程序的方法。请参见示例
bpf\u map\u\u重用\u fd()
。Bpftool支持重用现有映射,使用
Bpftool prog load
map
参数(请参阅)。例如,从
foo.o
加载一个程序,并告诉它对在对象文件中找到的第一个映射重用id
27
的映射,然后对对象文件中名为
foomap
的映射将映射固定在
/sys/fs/bpf/foomap

# bpftool prog load foo.o /sys/fs/bpf/foo_prog \
        map idx 0 id 27 \
        map foomap stats pinned /sys/fs/bpf/foomap

我可以通过各种可用的syscall实用程序在用户空间中访问映射,但目的是从不同附加类型的不同bpf程序(_kern.c)访问映射。