Добрый день всем.
Столкнулся с непонятным поведением одного старого сервера в нагрузочном тесте. При скорости входящего трафика в районе 300Мбит/с - полет нормальный, однако где-то после ~360Мбит - все прерывания собираются на одно ядро.
[root@cat ~]# uname --all
Linux cat 2.6.32-573.7.1.el6.x86_64 #1 SMP Tue Sep 22 22:00:00 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
[root@cat ~]# ethtool -i eth0
driver: e1000e
version: 3.2.5-k
firmware-version: 1.0-0
bus-info: 0000:04:00.0
[root@cat ~]# cat /proc/interrupts | grep eth
49: 3899076 3127071 3138498 3129201 3021226 3024870 3021558 3031263 PCI-MSI-edge eth0
[root@cat ~]# cat /proc/softirqs | grep RX
NET_RX: 13273515 20093759 20261881 20181581 11821256 11702301 11883894 11702684
[root@cat ~]# sysctl -a | grep -E 'netdev|backlog|weight'
net.core.dev_weight = 64
net.core.netdev_max_backlog = 1000
net.core.netdev_rss_key = 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
net.core.netdev_budget = 300
net.ipv4.tcp_max_syn_backlog = 2048
[root@cat ~]# cat /sys/class/net/eth0/queues/rx-0/rps_cpus
00
[root@cat ~]# cat /proc/irq/49/smp_affinity
ff
[root@cat ~]# ethtool -k eth0
Offload parameters for eth0:
rx-checksumming: on
tx-checksumming: on
scatter-gather: on
tcp-segmentation-offload: on
udp-fragmentation-offload: off
generic-segmentation-offload: on
generic-receive-offload: on
large-receive-offload: off
[root@cat~]# ethtool -c eth0
Coalesce parameters for eth0:
Adaptive RX: off TX: off
stats-block-usecs: 0
sample-interval: 0
pkt-rate-low: 0
pkt-rate-high: 0
rx-usecs: 3
rx-frames: 0
rx-usecs-irq: 0
rx-frames-irq: 0
tx-usecs: 0
tx-frames: 0
tx-usecs-irq: 0
tx-frames-irq: 0
rx-usecs-low: 0
rx-frame-low: 0
tx-usecs-low: 0
tx-frame-low: 0
rx-usecs-high: 0
rx-frame-high: 0
tx-usecs-high: 0
tx-frame-high: 0
[root@cat ~]# cat /proc/net/softnet_stat
1220c6f5 00000000 0005668a 00000000 00000000 00000000 00000000 00000000 00000000 005e1cce
126639dd 00000000 000352c3 00000000 00000000 00000000 00000000 00000000 00000000 00e07895
12955ce5 00000000 00032a67 00000000 00000000 00000000 00000000 00000000 00000000 00e2f100
1893a083 00000000 00083e69 00000000 00000000 00000000 00000000 00000000 00000000 00dccfe3
0e5324de 00000000 00040a2f 00000000 00000000 00000000 00000000 00000000 00000000 005fce5f
0c54c177 00000000 0002232b 00000000 00000000 00000000 00000000 00000000 00000000 006025ae
0c8125ea 00000000 00030479 00000000 00000000 00000000 00000000 00000000 00000000 00619b8c
13edcf79 00000000 00092307 00000000 00000000 00000000 00000000 00000000 00000000 005912cd
При выключенном RPS и трафике в 330Мбит загрузка CPU выглядит так:
Cpu0 : 33.3%us, 2.9%sy, 0.0%ni, 49.3%id, 0.0%wa, 0.0%hi, 14.5%si, 0.0%st
Cpu1 : 19.7%us, 12.7%sy, 0.0%ni, 66.2%id, 0.0%wa, 0.0%hi, 1.4%si, 0.0%st
Cpu2 : 7.4%us, 7.4%sy, 0.0%ni, 77.9%id, 5.9%wa, 0.0%hi, 1.5%si, 0.0%st
Cpu3 : 14.1%us, 23.9%sy, 0.0%ni, 54.9%id, 1.4%wa, 0.0%hi, 5.6%si, 0.0%st
Cpu4 : 42.9%us, 8.6%sy, 0.0%ni, 40.0%id, 0.0%wa, 0.0%hi, 8.6%si, 0.0%st
Cpu5 : 3.0%us, 1.5%sy, 0.0%ni, 92.5%id, 0.0%wa, 0.0%hi, 3.0%si, 0.0%st
Cpu6 : 28.0%us, 57.3%sy, 0.0%ni, 6.7%id, 0.0%wa, 0.0%hi, 8.0%si, 0.0%st
Cpu7 : 20.0%us, 41.4%sy, 0.0%ni, 28.6%id, 0.0%wa, 0.0%hi, 10.0%si, 0.0%st
При трафике 380Мбит:
Cpu1 : 5.9%us, 9.8%sy, 0.0%ni, 82.4%id, 2.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu2 : 0.0%us, 1.9%sy, 0.0%ni, 98.1%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu3 : 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu4 : 41.2%us, 37.3%sy, 0.0%ni, 21.6%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu5 : 0.0%us, 0.0%sy, 0.0%ni, 98.0%id, 2.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu6 : 3.8%us, 7.5%sy, 0.0%ni, 88.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu7 : 0.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi,100.0%si, 0.0%st
Соответственно все отложенные прерывания собираются на одном ядре.
При этом обычные прерывания в interrupts для eth0 в этот момент останавливаются. Нагуглил, что при превышении budget в NAPI переключается обработка пакетов на отложенные прерывания, как «более дешевые». Однако на деле это оказывается не так.
Что пробовал сделать:
1) Включать RPS (первоначально он и был включен, но с ним нагрузка при трафике в 330Мбит выше, чем без) на все ядра, на все ядра кроме того, на которое заведены прерывания сетевой карты, попроцессорно
2) Менять маску smp_affinity в разных вариациях - на все ядра, попроцессорно, на одно ядро.
3) Увеличивать netdev_max_backlog, netdev_budget, netdev_weight и другие.
4) Менять режимы rx-usecs
В итоге всех изменений где-то меньше теряется пакетов, где-то загрузка CPU поменьше, но главное не меняется - после пересечения рубежа в ~350Мбит прекращают тикать interrupts сетевой карты, а все softirqs собираются на каком-то одном (случайном) ядре.
Подскажите, в какую сторону копать?