Разнесение сетевых очередей по прерываниям на пограничных маршрутизаторах
Значительную долю нагрузки на процессоры шлюзов составляют прерывания, генерируемые сетевыми картами как сигнал на заполнение буфера устройства пакетами данных. Современные сетевые карты имеют несколько очередей (буферов) пакетов, как входящих, так и исходящих, с выделенными прерываниями для каждой очереди. По умолчанию все прерывания от всех очередей всех сетевых карт обрабатываются первым ядром, что, очевидно, быстро приводит к его перегрузке и, как следствие неспособности обработать прерывания, потерям пакетов.
Решение данной проблемы заключается в разнесении прерываний от разных устройств на разные процессорные ядра.
Ниже приведён пример таблицы прерываний 4-x ядерного сервера с двумя сетевыми интерфейсами, каждый из которых имеет по одной исходящей (tx) и входящей (rx) очереди:
CPU0 CPU1 CPU2 CPU3 46: 0 0 2522395854 0 PCI-MSI-edge eth1-rx-0 47: 0 0 0 3223164197 PCI-MSI-edge eth1-tx-0 48: 3194 0 0 0 PCI-MSI-edge eth1 49: 0 0 0 1519085293 PCI-MSI-edge eth2-rx-0 50: 0 0 1572863429 0 PCI-MSI-edge eth2-tx-0 51: 3142 0 0 0 PCI-MSI-edge eth2
Как мы можем видеть, незначительное количество прерываний генерируется самими интерфейсами (eth1,eth2). Эти прерывания не имеют отношения к трафику. Основная же масса прерываний распределена по очередям rx и tx. В целях оптимизации использования процессорного кеша рекомендуется, в случае, когда данные входят в один интерфейс и уходят с другого (FORWARD), обрабатывать прерывания rx первого и tx второго на одном ядре, что и имеет место быть в данном примере. Чтобы привязать прерывания к ядрам так, как показано в примере, надо выполнить следующее:
echo "4" > /proc/irq/46/smp_affinity echo "8" > /proc/irq/47/smp_affinity echo "8" > /proc/irq/49/smp_affinity echo "4" > /proc/irq/50/smp_affinity
Ядра здесь имеют следующие номера:
- CPU0 - 1
- CPU1 - 2
- CPU2 - 4
- CPU3 - 8