即使使用了编译指示展开,BPF验证程序也会由于后端而拒绝XDP程序

时间:2019-07-03 14:32:55

标签: c clang llvm-clang ebpf

因此,按照标题,我正在尝试加载XDP程序,当bpf验证程序出人意料地因著名的 后沿 错误而踢到我的脸上时, :

libbpf: load bpf program failed: Invalid argument
libbpf: -- BEGIN DUMP LOG ---
libbpf: 
back-edge from insn 271 to 69

libbpf: -- END LOG --
libbpf: failed to load program 'xdp_prog'

即使在我受限的ebpf C代码中,唯一的for循环(在编译时已知迭代次数)也受pragma unroll保护。这是一个代码片段,显示了__alwais_inline d函数中定义的受影响的for循环:

#pragma unroll
for (i = 0; i < 8; i++)
{
    int k = idx + i;
    mask = bpf_map_lookup_elem(&a_map, &k);
    if (!mask || (mask->an_idx == 0))
        return -1;

    *m_key = *key;
    foo(m_key, mask);  // an __alwais_inline func

    id = bpf_map_lookup_elem(&b_map, m_key);
    if (id)
    {
        *out_id = *id;
        return 0;
    }
}

也许是clang无法展开循环的问题?如果正确,为什么会失败,是否有任何解决方法?手动展开循环是不可接受的,因为它会导致可怕,不可维护且难以读取的代码。

哦,我在工作:

  • 内核4.19.3
  • llvm-clang 8

有什么想法吗?

更新
只是注意到,甚至以下虚拟的for循环似乎也没有展开,而bpf验证程序抱怨后端:

#pragma unroll
for (i = 0; i < 8; i++)
{
    int k = i;
    mask = bpf_map_lookup_elem(&a_map, &k);
}

是我吗,这没有任何意义?

1 个答案:

答案 0 :(得分:0)

我编写了以下代码,并且可以正常工作。

#pragma clang loop unroll(full)
for (int i = 0; i < 128; i++)
{
    if (bpf_map_lookup_elem(&conntrack_hash_tab, &reply_key) == NULL)
    {
        break;
    }
    reply_key.dport = reply_key.dport+1;
}