【发布时间】:2019-09-30 02:54:06
【问题描述】:
我正在考虑在内核中复制数据包并转发到 5 个主机(单播)的解决方案。计划为此使用 eBPF/XDP。
我尝试循环 5 次,在循环内我计划克隆数据包,修改 DST IP 地址,更新 cksum 并在收到的同一 intf 上发送数据包。
我在某处读到不能在 XDP 中使用循环,所以不确定这是否可行?
请需要专家的建议。
【问题讨论】:
标签: llvm-clang bpf ebpf
我正在考虑在内核中复制数据包并转发到 5 个主机(单播)的解决方案。计划为此使用 eBPF/XDP。
我尝试循环 5 次,在循环内我计划克隆数据包,修改 DST IP 地址,更新 cksum 并在收到的同一 intf 上发送数据包。
我在某处读到不能在 XDP 中使用循环,所以不确定这是否可行?
请需要专家的建议。
【问题讨论】:
标签: llvm-clang bpf ebpf
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 ... */
}
这意味着在生成的目标文件中,函数将被展开,它将被要执行的完整系列指令替换,没有实际的向后跳转。
目前对于具有任意数量循环的序列没有解决方案。
【讨论】:
对于 Linux
从技术上讲,BPF 字节码程序的控制流图中的后端是被禁止的,而不是循环。具体来说,这意味着您可以在 C 中编写有界循环,但您必须在编译时展开它们。
要展开循环,您可以使用Clang's #pragma unroll directive。这应该适用于 5 次迭代的循环,但不适用于很长的循环。
【讨论】: