我使用tc将我的eBPF (使用clang编译的C代码)附加到网络中。
我使用eBPF地图来存储一些数据。
具体来说,我正在使用bpf_map_update_elem从BPF程序中更新eBPF地图,但我也希望在程序之外更改映射from的内容。
映射<#>结构:
struct rt_val {
int ifaceno;
int macaddr[6];
};
union key_4 {
__u32 b32[2];
__u8 b8[8];
};
struct bpf_map_def SEC("maps") lpm_map_fwd = {
.type = BPF_MAP_TYPE_LPM_TRIE,
.key_size = 8,
.value_size = sizeof(struct rt_val),
.max_entries = 50,
.map_flags = BPF_F_NO_PREALLOC,
};地图更新和查找都很好。
但是我想从程序执行之外动态地更改eBPF映射的内容。
关于这个问题的任何评论/建议都是appreciated!
资源:
系统细节:
uname -r:4.15.0-47-通用OS:Ubuntu 18发布于 2019-04-23 09:10:31
您已经找到了从用户空间更新eBPF映射所需的所有工具。
bpf()bpf(cmd, attr, size)系统调用用于执行更新。作为第一个参数传递的cmd指示要执行何种类型的操作:在您的情况下,这将是BPF_MAP_UPDATE_ELEM。然后,您链接的手册页解释了如何构建attr:在您的示例中(对于地图更新),它应该是:
struct { /* Used by BPF_MAP_*_ELEM and BPF_MAP_GET_NEXT_KEY commands */
__u32 map_fd;
__aligned_u64 key;
union {
__aligned_u64 value;
/* [...] */
};
__u64 flags;
};这意味着您应该构建一个union bpf_attr,并将文件描述符传递给映射、要更新的条目的键、该键的新值以及可能的一些标志。
可以获得映射的文件描述符:
bpf()系统调用,使用BPF_MAP_GET_FD_BY_ID命令,bpf()的调用的返回值,但在使用tc加载程序的情况下不是这样)。请注意,libbpf (随内核运出或镜像在GitHub上)提供了bpf()系统调用的包装器,可以使事情变得更简单。
实际上,您不需要重新实现所有这些。正如您在标题中提到的,bpftool允许您从命令行更新映射,而不必重新实现整个过程。
编辑:在Ubuntu19.10 (eoan)上,bpftool被打包为linux-tools-common包的一部分。有关旧版本的说明,请参阅下面。
在本文撰写之时,bpftool已经为Debian/Ubuntu打包了不,这意味着您必须从源代码构建它。它是随内核一起提供的,所以下载起来需要时间,但是构建实际上非常简单:
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
$ cd linux
$ cd tools/bpf/bpftool
$ make
(# make install)
(# make doc doc-install)或者,有一个非官方版本打包的在这页上 (免责声明:从我的公司)。打包的二进制文件是静态构建的,应该可以在所有x86_64 Linux机器上工作。
在此之后,您可以使用它列出系统上当前存在的映射:
# bpftool -f map show每个地图的ids将显示在左边。查找与您要更新的地图相关的id (或者如果该地图被固定,请注意其路径,并使用-f选项显示),然后使用以下之一:
# bpftool map update id key value
# bpftool map update pinned key value 例如:
# bpftool map update id 17 key 0x1 0 0 0 0 0 0 0 value 0x1 0x2 0x3...(注:我会使用__u8s的数组,而不是ints来存储struct rt_val中的MAC地址。您的macaddr可能会计算24个字节。)
如果您不确定如何将值存储在映射中,请毫不犹豫地将其转储到控制台中:
# bpftool map dump id 17我不知道任何现有的bpftool教程,但是您可以找到该工具的所有细节在手册中。我还写了一些关于它的提示,在Twitter上。
https://askubuntu.com/questions/1134896
复制相似问题