bpf()

bpf()

我正在tc使用增强型BPF(使用 clang 编译的 C 代码),连接到网络。

我在用eBPF 地图存储一些数据。

具体来说,我正在使用bpf_map_update_elem来更新eBPF 地图在 BPF 程序中,但我还想更改地图的内容从外面该程序。

地图结构

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 Map 的内容。

任何关于此问题的评论/建议感谢!

资源:

系统规格:

  • uname -r:4.15.0-47-通用
  • OS:Ubuntu 18

答案1

您已经找到了从用户空间更新 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 虚拟文件系统下的路径,如果地图已被预先固定,
  • 从地图的 ID,再次调用bpf()系统调用,使用BPF_MAP_GET_FD_BY_ID命令,
  • bpf()(或者作为创建地图的调用的返回值,但在使用 tc 加载程序的情况下则不然)。

请注意 libbpf (随内核一起提供或者GitHub 上的镜像) 提供了bpf()系统调用的包装器,可以使事情变得更容易。

bpf工具

实际上,您不需要重新实现所有这些。正如您在标题中提到的,bpftool 允许您从命令行更新地图,而无需重新实现整个过程。

获取 bpftool

编辑:在 Ubuntu 19.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

每个地图的 ID 将显示在左侧。找到与要更新的地图相关的 ID(或者,如果地图已固定,请注意其路径,与选项一起显示-f),然后使用以下方法之一:

# bpftool map update id <id> key <key> value <new_value>
# bpftool map update pinned <path> key <key> value <new_value>

例如:

# bpftool map update id 17 key 0x1 0 0 0 0 0 0 0 value 0x1 0x2 0x3...

(注意:我将使用 s 数组__u8而不是ints 来存储 MAC 地址struct rt_val。您的MAC 地址macaddr可能计为 24 个字节。)

如果您不确定值如何存储在地图中,请毫不犹豫地将其转储到控制台中:

# bpftool map dump id 17

更多资源

我不知道有任何现有的 bpftool 教程,但你可以找到所有详细信息在手册页中了解该工具。我还写了一些关于它的提示在 Twitter 上

相关内容