BPF-верификатор отклоняет программу XDP из-за back-edge, хотя используется прагма unroll - PullRequest
0 голосов
/ 03 июля 2019

Итак, в соответствии с заголовком я пытаюсь загрузить программу XDP, когда неожиданно bpf-верификатор начинает выплевывать мне в лицо знаменитую back-edge ошибку:

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'

Несмотря на то, что единственный цикл for - с числом итераций, известным во время компиляции - в моем ограниченном коде ebpf C защищен pragma unroll. Вот фрагмент кода, показывающий задействованный цикл for, определенный в функции __alwais_inline d:

#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

Есть мысли?

UPDATE
Только что заметил, что даже следующий фиктивный цикл for, похоже, не развернут, поскольку верификатор bpf жалуется на back-edge:

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

Разве только я для этого не имеет никакого смысла?

...