Linux 的 BPF 程序中是否允许循环?

Are loops allowed in Linux's BPF programs?

我正在考虑在内核中复制数据包并转发到5台主机(单播)的解决方案。计划为此使用 eBPF/XDP。

我正在尝试循环 5 次,在循环内我计划克隆数据包、修改 DST IP 地址、更新校验和并在接收到的同一个 intf 上发送数据包。

我在某处读到 XDP 中不能使用循环,所以不确定这是否可行?

请专家指教。

对于Linux <5.3:

从技术上讲,back-edges在BPF字节码程序的控制流图中是禁止的,不是循环。具体来说,这意味着您可以在 C 中编写有界循环,但是您必须在编译时展开它们

要展开循环,您可以使用Clang's #pragma unroll directive。这应该适用于 5 次迭代循环,但不适用于很长的循环。

编辑 2019 年 6 月: 有界循环 现已登陆内核,可用 Linux 5.3 (commit).

原回答:

不,目前 eBPF 程序中不允许循环。不允许后沿,以便内核验证者可以确保程序终止(并且不会挂起内核)。

这在未来可能会改变,因为内核开发人员正在努力support for bounding loops

两个可能的解决方法值得一提。 两者都假设您知道在编写程序时需要“循环”多少次

首先,关于函数,后边有一个例外。这意味着您可以拥有功能,并多次调用它们。因此,您可以将通常放在循环中的所有内容放在一个单独的函数中,并在循环中多次调用此函数。

第二件事是您实际上可以在 C 代码中 编写 循环,并在编译时要求 clang 展开它们。这看起来像下面这样:

#pragma clang loop unroll(full)
        for (i = 0; i < 4; i++) {
            /* Do stuff ... */
        }

这意味着在生成的目标文件中,函数将展开,它将被要执行的完整系列指令所取代,没有实际的向后跳转。

目前没有解决任意循环数的问题。