【问题标题】:Are loops allowed in Linux's BPF programs?Linux 的 BPF 程序中是否允许循环?
【发布时间】:2019-09-30 02:54:06
【问题描述】:

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

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

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

请需要专家的建议。

【问题讨论】:

    标签: llvm-clang bpf ebpf


    【解决方案1】:

    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 ... */
            }
    

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

    目前对于具有任意数量循环的序列没有解决方案。

    【讨论】:

    • $ sudo ip link set dev enp0s8 xdp object loop.o sec test_loop Prog section 'test_loop' 被拒绝:无效参数 (22)! - 类型:6 - 说明:15(0 超出限制) - 许可证:验证程序分析:从 insn 12 到 3 的后端错误获取程序/地图!
    • SEC("test_loop") int loop() { int i = 0; #pragma clang loop unroll(full) for (i = 0; i
    • 对不起,我用优化“-O2”选项编译,它成功了。谢谢。
    【解决方案2】:

    对于 Linux

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-13
      • 2020-12-27
      • 1970-01-01
      • 2017-04-27
      相关资源
      最近更新 更多