Назад | Перейти на главную страницу

Сервер Linux отбрасывает пакеты RX в __netif_receive_skb_core

У меня есть сервер Ubuntu 18.04, который отбрасывает полученные пакеты, и я не могу понять, почему.

Вот график отброшенных пакетов из netdata:

На сервере работает несколько контейнеров докеров и сетей, поэтому имеется несколько мостов Linux и интерфейсов veth. Однако проблема связана с физическим интерфейсом. Нет настроенных VLAN.

На машине нет правил IPtables, кроме тех, которые создаются Docker.

Сетевая карта - это Intel I210 (igb Водитель).

Копирование данных через TCP (rsync) работает на линейной скорости 1 Гбит / с, поэтому не многие TCP-пакеты могут быть повреждены. (Я ожидал, что падение TCP сильно повредит производительности передачи из-за уменьшения размера окна.)

# uname -a
Linux epyc 5.3.0-51-generic #44~18.04.2-Ubuntu SMP Thu Apr 23 14:27:18 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

RX-DRP можно увидеть на eno1, который является единственным физическим интерфейсом, который есть на машине. Он увеличивается с прибл. 2 пакета / сек с очень низким трафиком (admin ssh, только несколько DNS-запросов).

# netstat -ni
Kernel Interface table
Iface      MTU    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg
br-69eb0  1500    45768      0      0 0         41072      0      0      0 BMRU
br-bf2c7  1500       71      0      0 0            85      0      0      0 BMRU
br-f4e34  1500   187676      0      0 0        192128      0      0      0 BMRU
docker0   1500    62739      0      0 0         70194      0      0      0 BMRU
eno1      1500 55517866      0 271391 35     19796132      0      0      0 BMRU
lo       65536     7381      0      0 0          7381      0      0      0 LRU
veth078d  1500    40657      0      0 0         48148      0      0      0 BMRU
veth231e  1500     2582      0      0 0          2323      0      0      0 BMRU
veth2f4f  1500       19      0      0 0           164      0      0      0 BMRU

Настройки сетевой карты (ethtool)

Я попытался отключить все настройки разгрузки оборудования RX, которые я мог редактировать, но это не помогло.

Увеличил буферы, тоже не помогло.

# ethtool -S eno1 | grep rx
     rx_packets: 55580744
     rx_bytes: 76852450760
     rx_broadcast: 294019
     rx_multicast: 228993
     rx_crc_errors: 0
     rx_no_buffer_count: 0
     rx_missed_errors: 0
     rx_long_length_errors: 0
     rx_short_length_errors: 0
     rx_align_errors: 0
     rx_flow_control_xon: 0
     rx_flow_control_xoff: 0
     rx_long_byte_count: 76852450760
     rx_smbus: 66009
     os2bmc_rx_by_bmc: 19137
     os2bmc_rx_by_host: 190
     rx_hwtstamp_cleared: 0
     rx_errors: 0
     rx_length_errors: 0
     rx_over_errors: 0
     rx_frame_errors: 0
     rx_fifo_errors: 35
     rx_queue_0_packets: 16271369
     rx_queue_0_bytes: 22437386945
     rx_queue_0_drops: 0
     rx_queue_0_csum_err: 0
     rx_queue_0_alloc_failed: 0
     rx_queue_1_packets: 5913593
     rx_queue_1_bytes: 6458814275
     rx_queue_1_drops: 0
     rx_queue_1_csum_err: 1
     rx_queue_1_alloc_failed: 0
     rx_queue_2_packets: 29208019
     rx_queue_2_bytes: 42357497354
     rx_queue_2_drops: 35
     rx_queue_2_csum_err: 0
     rx_queue_2_alloc_failed: 0
     rx_queue_3_packets: 4121883
     rx_queue_3_bytes: 5366292094
     rx_queue_3_drops: 0
     rx_queue_3_csum_err: 0
     rx_queue_3_alloc_failed: 0

# ethtool -k eno1 | grep -vE 'tx|fixed'
Features for eno1:
rx-checksumming: off
scatter-gather: off
tcp-segmentation-offload: off
udp-fragmentation-offload: off
generic-segmentation-offload: off
generic-receive-offload: off
rx-vlan-offload: off
ntuple-filters: off
receive-hashing: off
rx-all: off
hw-tc-offload: on

# ethtool -g eno1
Ring parameters for eno1:
Pre-set maximums:
RX:     4096
RX Mini:    0
RX Jumbo:   0
TX:     4096
Current hardware settings:
RX:     256
RX Mini:    0
RX Jumbo:   0
TX:     256

Dropwatch

Из этот блог Я нашел инструмент секундомер, что дает следующий результат:

# sudo ./dropwatch -l kas
Initalizing kallsyms db
dropwatch> start
Enabling monitoring...
Kernel monitoring activated.
Issue Ctrl-C to stop monitoring
6 drops at __netif_receive_skb_core+4a0 (0xffffffff979002d0)
1 drops at icmpv6_rcv+310 (0xffffffff97a2e6a0)
1 drops at ip_rcv_finish_core.isra.18+1b4 (0xffffffff97976644)
1 drops at __udp4_lib_rcv+a34 (0xffffffff979b0fc4)
3 drops at __udp4_lib_rcv+a34 (0xffffffff979b0fc4)
1 drops at unix_release_sock+1a7 (0xffffffff979f9977)
1 drops at unix_release_sock+1a7 (0xffffffff979f9977)
1 drops at sk_stream_kill_queues+4d (0xffffffff978eeffd)
2 drops at unix_stream_connect+2e5 (0xffffffff979fae75)
12 drops at __netif_receive_skb_core+4a0 (0xffffffff979002d0)
1 drops at sk_stream_kill_queues+4d (0xffffffff978eeffd)
1 drops at sk_stream_kill_queues+4d (0xffffffff978eeffd)
2 drops at __udp4_lib_rcv+a34 (0xffffffff979b0fc4)
2 drops at unix_stream_connect+2e5 (0xffffffff979fae75)
6 drops at ip_forward+1b5 (0xffffffff97978615)
1 drops at unix_release_sock+1a7 (0xffffffff979f9977)
1 drops at __udp4_lib_rcv+a34 (0xffffffff979b0fc4)
1 drops at sk_stream_kill_queues+4d (0xffffffff978eeffd)
1 drops at sk_stream_kill_queues+4d (0xffffffff978eeffd)
2 drops at unix_stream_connect+2e5 (0xffffffff979fae75)
2 drops at unix_stream_connect+2e5 (0xffffffff979fae75)
1 drops at unix_release_sock+1a7 (0xffffffff979f9977)
12 drops at __netif_receive_skb_core+4a0 (0xffffffff979002d0)
6 drops at ip_forward+1b5 (0xffffffff97978615)
1 drops at tcp_v6_rcv+16c (0xffffffff97a3829c)
2 drops at unix_stream_connect+2e5 (0xffffffff979fae75)
12 drops at __netif_receive_skb_core+4a0 (0xffffffff979002d0)
1 drops at sk_stream_kill_queues+4d (0xffffffff978eeffd)
2 drops at unix_stream_connect+2e5 (0xffffffff979fae75)
^C

Я прочитал это, поскольку большинство падений происходит в __netif_receive_skb_core.

В Руководство по настройке производительности сети Red Hat Enterprise Linux говорит (глава «Очередь адаптера»):

В netif_receive_skb() Функция ядра найдет соответствующий ЦП для пакета и поставит пакеты в очередь этого ЦП. Если очередь для этого процессора заполнена и уже имеет максимальный размер, пакеты будут отброшены. Чтобы настроить этот параметр, сначала определите, нужно ли увеличивать объем невыполненной работы. В /proc/net/softnet_stat файл содержит счетчик во 2-м столбце, который увеличивается при переполнении очереди невыполненных работ netdev. Если это значение увеличивается со временем, тогда netdev_max_backlog нужно увеличить.

Увеличение netdev_max_backlog не помогло, но это привело меня к SoftIRQ:

SoftIRQ

Согласно документу Red Hat, у SoftIRQ есть несколько интересных аспектов:

# cat /proc/net/softnet_stat
00024f83 00000000 000000e8 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
000152c0 00000000 0000008d 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00010238 00000000 00000061 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00010d8c 00000000 00000081 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
000f3cb3 00000000 00000d83 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
0009e391 00000000 0000050d 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
0025265b 00000000 00001023 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00111a24 00000000 0000095a 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
008bcbf0 00000000 0000355d 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
004875d8 00000000 00002408 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
0001c93c 00000000 000000cc 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00025fdb 00000000 000000fa 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
0005d1e5 00000000 000005f2 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
000f9bfd 00000000 00000b9e 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
000448bc 00000000 00000407 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00044f25 00000000 00000415 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

Как видите, 2-й столбец всегда равен 0, что не соответствует приведенному выше утверждению о netif_receive_skb(), но я вижу постоянно увеличивающиеся значения в 3-й столбец.

Это описано в «Промахи SoftIRQ». Опять же, цитируя документ Red Hat:

Иногда необходимо увеличить время, в течение которого SoftIRQ может выполняться на ЦП. Это известно как netdev_budget. Значение бюджета по умолчанию - 300. Это значение можно удвоить, если в 3-м столбце /proc/net/softnet_stat увеличивается, что указывает на то, что SoftIRQ не получил достаточно процессорного времени

Надо увеличивать net.core.netdev_budget до 600. Ничего не изменилось.

Другие вещи, которые я пробовал

Статистика по-прежнему показывает трафик BMC на общем интерфейсе. С тех пор я пытался переместить BMC в специальный интерфейс, но это не улучшило ситуацию.

Этот документ by SuSE дает некоторые законные причины для отбрасывания пакетов и метод подтверждения того, что отбрасывания безвредны: они должны исчезнуть при установке интерфейса в режим PROMISC, поскольку они вызваны неизвестными протоколами или неправильными тегами VLAN. Я включил промисковый режим, но пакеты все равно сбрасываются.

Подозревая, что кадры большого размера слишком большие, я изменил размер MTU на 9000. Это не помогло.

Я наконец нашел источник проблемы: это фреймы Ethernet с неизвестным типом Ethernet. Я думал, что эти капли должны исчезнуть в режиме PROMISC, но, очевидно, этого не происходит.

В моем случае это был ethertype 0x8912 и 0x88e1 фреймы, отправленные маршрутизатором AVM FritzBox для обнаружения адаптеров Poweline. Чтобы подтвердить, я блокирую эти кадры через nftables с этим набором правил в /etc/nftables.conf:

table netdev filter {
    chain ingress {
        type filter hook ingress device eno1 priority 0; policy accept;
        meta protocol {0x8912, 0x88e1} drop
    }
}

После этого пропали дропы сети! Даже если они не заблокированы, они безвредны и не будут мешать работе моего сервера. Я все равно буду держать их заблокированными, чтобы мониторинг был чистым и видел реальные падения интерфейса / проблемы с производительностью.

Дополнительную информацию об этих рамах можно найти здесь: