Почему этот код eBPF выходит из строя при больших объемах трафика?

#ebpf

Вопрос:

Я пытаюсь настроить сетевой фильтр, который удаляет теги VLan при входе в tc( tc filter add dev ethx ingress bpf da obj... ) и добавляет те же теги VLan при выходе из маршрута ( ip route add default encap bpf headroom 14 xmit obj... dev ethx table xxx ) в соответствии с 4-кортежами TCP.

Поскольку на выходе из маршрута отсутствует заголовок L2, я звоню bpf_skb_change_head , чтобы добавить заголовок L2 для skb, как показано ниже:

 unsigned short headers[7];
memcpy(headers, pm->p_s_mac, 6);                                  //fill the source mac from previous
memcpy(headers   3, pm->p_d_mac, 6);                              //fill the destination mac from previous
headers[6] = eth_p_proto;                                         //set the proto type to ipv4(0x0800)
bpf_skb_change_head(skb, sizeof(headers), 0);                     //reserve the space for mac header
bpf_skb_store_bytes(skb, 0, (void *)headers, sizeof(headers), 0); //fill the mac header
bpf_redirect(skb->ifindex, 0);                                    //send to egress NIC directly
 

Приведенные выше коды хорошо работают в большинстве сред, но когда трафик превышает 6~7 Гбит / с(всего 10 Гбит / с) на одной сетевой карте, вся система запаникует и перезагрузится без какой-либо полезной выходной информации. Комментируя некоторые из этих функций, я могу быть уверен, что сбой был вызван bpf_skb_change_head . Кто-нибудь знает об этой проблеме или дает какие-либо советы?

Комментарии:

1. Какое ядро вы используете? Вы проверяли свои системные журналы на наличие каких-либо следов стека ядра? Этого не должно произойти, и, скорее всего, это ошибка в вашем ядре.

2. Спасибо за напоминание, я пробовал ядро 5.4.124, 5.4.144 и 5.10.40 с системами Debian, там также были такие же сбои, без какого-либо вывода в системный журнал или консоль.