不同 ebpf 程序类型之间的映射共享 [英] Map sharing between different ebpf program types

查看:29
本文介绍了不同 ebpf 程序类型之间的映射共享的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Is it possible to share ebpf maps between different program types. I need to share a map between a tc-bpf program and a cgroup bpf program. This should be possible if the map is pinned to file system that act as global namespace. But, I haven't got this working.

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

The map is created by tc-bpf program and pinned to global namespace. Since it is tc-bpf program, the map is of type struct bpf_elf_map. This bpf program is loaded via 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.

Now, I have a cgroup bpf program that should be accessing this map, but since it is loaded via a user.c (libbpf) or bpftool and not iproute, the map that is defined here cannot be ‘bpf_elf_map’, but it is struct bpf_map_def. So in the cgroup bpf program, the same map is defined as struct bpf_map_def and not struct bpf_elf_map.

可能正因为如此,当我转储地图(并且不共享预期的地图)时,cgroup 程序会获得一个新的 map_id,理想情况下,当同一个地图在 bpf 程序之间共享时,这些 bpf 程序将具有相同的 map_id 关联使用他们独特的 prog_ids.

Probably because of this the cgroup program gets a new map_id when I dump the maps (and does not share the intended map), ideally when the same map is shared across bpf programs, these bpf programs would be having the same map_id associated with their unique prog_ids.

推荐答案

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

It is possible to share access to eBPF maps between programs of different types.

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

First, you can forget about those differences between struct bpf_elf_map and struct bpf_map_def. They are structs used in user space to build the objects to pass to the kernel. Iproute2 and libbpf may not use the same struct/attribute names, but they both end up passing the map metadata to the bpf() system call in the same format, or the kernel would not understand what map is to be created.

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

When they are loaded to the kernel, eBPF programs refer to a given map through file descriptors to this map. This means that the process calling the bpf() system call to load the program first has to retrieve file descriptors to the map to use. So the two following cases may happen:

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

  • User space application (ip, tc, bpftool...) parses the ELF object file and collects map-related metadata. It does not identify (and possibly did not even try to identify) any existing map that should be reused for the program. So it creates a new map with the bpf() syscall, which returns a file descriptor to this newly-created map. This file descriptor is used in the program instructions referring to map access (once the program is loaded in the kernel, those file descriptors will be replaced by the map address), and the program is then loaded with the bpf() syscall. This is what happens with your tc program, and in your case it seems, with your cgroup program which is creating a second map.

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

Or user application parses the ELF object file, and finds somehow that there is already an existing map that the program should use. For example, it finds a map of id 1337, or a pinned map under /sys/fs/bpf/. In that case it retrieves a file descriptor to that map (from the id with bpf() syscall, from a pinned path with open()). Then as in the first case, it uses this file descriptor to prepare and then load the program.

Libbpf 提供了一种方法来重用给定映射的文件描述符以供程序使用.参见示例 bpf_map__reuse_fd().bpftool 使用它来支持重用现有的地图,map 参数用于 bpftool prog load(参见 man bpftool-prog).例如,从 foo.o 加载一个程序并告诉它重用 id 27 的映射作为在目标文件中找到的第一个映射,然后映射固定在 /sys/fs/bpf/foomap 用于目标文件中名为 foomap 的映射:

Libbpf provides a way to reuse a file descriptor for a given map to use with a program. See for example bpf_map__reuse_fd(). Bpftool uses it to support reusing existing maps, with the map argument for bpftool prog load (see man bpftool-prog). For example, load a program from foo.o and tell it to reuse map of id 27 for the first map found in the object file, then the map pinned at /sys/fs/bpf/foomap for the map named foomap in the object file:

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

这篇关于不同 ebpf 程序类型之间的映射共享的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆