NAT производительность

Решил выяснить сколько трафика сможет занатить один Linux сервер, какая нагрузка будет при этом на CPU.

Выяснилось, что при одном и том, же сетевом трафике, но разном количестве пакетов нагрузка на CPU будет разная, что совершенно логично.

Приведу тестовые данные:

Итак тестовая система:
Однопроцессорный четырехядерный сервер Intel(R) Xeon(R) CPU E5405 2.00GHz
Сетевые адаптеры Broadcom NetXtreme II BCM5708 1000Base-T (B2) PCI-X 64-bit 133MHz
ОС CentOS 5.4

Правила для iptables простые /etc/sysconfig/iptables


*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT DROP [0:0]

COMMIT

*nat

-A POSTROUTING -o eth0 -s 172.16.1.0/24 -j SNAT --to 192.168.0.1
-A POSTROUTING -o eth0 -s 172.16.2.0/24 -j SNAT --to 192.168.0.2
-A POSTROUTING -o eth0 -s 172.16.3.0/24 -j SNAT --to 192.168.0.3
--//--
-A POSTROUTING -o eth0 -s 172.16.254.0/24 -j SNAT --to 192.168.0.254

COMMIT

Пропустим через сервер трафик порядка 100 мегабит:

Входящий 90-100 мбит/с
Исходящий 50-60 мбит/с

Посмотрим количество пакетов:

vnstat -tr 15 -i eth0
409452 packets sampled in 15 seconds
Traffic average for eth0

rx 11291.52 kB/s 14072 packets/s
tx 5771.39 kB/s 13223 packets/s

Нагрузка на процессоры:

Cpu0 : 0.0%us, 0.0%sy, 0.0%ni, 91.0%id, 0.0%wa, 1.7%hi, 7.3%si, 0.0%st
Cpu1 : 0.0%us, 0.0%sy, 0.0%ni, 88.3%id, 0.0%wa, 3.7%hi, 8.0%si, 0.0%st

Количество соединений:

sysctl -a | grep ip_conntrack_count
net.ipv4.netfilter.ip_conntrack_count = 65405

Как видим нагрузка на каждый из процессоров всего в районе 7-8 процентов.

Увеличим трафик проходящий через сервер трафик до 200 мбит/с посмотрим как изменится картина

Трафик на обоих сетевых интерфейсах:
Входящий 200-230 мбит/с
Исходящий 130-150 мбит/с


vnstat -tr 15 -i eth0
873819 packets sampled in 15 seconds
Traffic average for eth0

rx 22922.61 kB/s 29719 packets/s
tx 14199.36 kB/s 28535 packets/s

Нагрузка на CPU

Cpu0 : 0.0%us, 0.0%sy, 0.0%ni, 68.0%id, 0.0%wa, 2.3%hi, 29.7%si, 0.0%st
Cpu1 : 0.0%us, 0.0%sy, 0.0%ni, 60.0%id, 0.0%wa, 4.7%hi, 35.0%si, 0.0%st

Увеличим трафик проходящий через сервер трафик до 350 мбит/с посмотрим как изменится картина

Трафик на обоих сетевых интерфейсах:
Входящий 350-370 мбит/с
Исходящий 190-210 мбит/с


vnstat -tr 15 -i eth0
1475987 packets sampled in 15 seconds
Traffic average for eth0

rx 37181.86 kB/s 49891 packets/s
tx 20991.49 kB/s 48507 packets/s

Нагрузка на CPU

Cpu0 : 0.0%us, 0.0%sy, 0.0%ni, 37.9%id, 0.0%wa, 1.7%hi, 60.5%si, 0.0%st
Cpu1 : 0.0%us, 0.0%sy, 0.0%ni, 19.5%id, 0.0%wa, 5.3%hi, 75.2%si, 0.0%st

Количество сетевых соединений

sysctl -a | grep ip_conntrack_count
net.ipv4.netfilter.ip_conntrack_count = 215402

Ну вот в принципе и все, как видим, даже обычный сервер в состоянии «заNATить» порядка 400 мегабит трафика.

Сетевой адаптер Intel ServerAdapter 1000 ET Quad Port PCIe в CentOS 5

Купили такую железку Intel ServerAdapter 1000 ET Quad Port PCIe .

Смонтировали в сервер. Задача заставить данный адаптер работать в CentOS 5, и распределить сетевую нагрузку по нескольким очередям.

Загружаемся:

Информация в dmesg


Intel(R) Gigabit Ethernet Network Driver - version 1.3.16-k2
Copyright (c) 2007-2009 Intel Corporation.
ACPI: PCI Interrupt 0000:09:00.0[A] -> GSI 17 (level, low) -> IRQ 169
PCI: Setting latency timer of device 0000:09:00.0 to 64
EDAC MC0: Giving out device to i5000_edac.c I5000: DEV 0000:00:10.0
intel_rng: FWH not detected
ACPI: PCI Interrupt 0000:00:1f.3[B] -> GSI 20 (level, low) -> IRQ 162
igb 0000:09:00.0: Intel(R) Gigabit Ethernet Network Connection
igb 0000:09:00.0: eth2: (PCIe:2.5Gb/s:Width x4) 00:1b:21:3e:ae:28
igb 0000:09:00.0: eth2: PBA No: e64750-002
igb 0000:09:00.0: Using MSI-X interrupts. 4 rx queue(s), 1 tx queue(s)
ACPI: PCI Interrupt 0000:09:00.1[B] -> GSI 18 (level, low) -> IRQ 106
PCI: Setting latency timer of device 0000:09:00.1 to 64
igb 0000:09:00.1: Intel(R) Gigabit Ethernet Network Connection
igb 0000:09:00.1: eth2: (PCIe:2.5Gb/s:Width x4) 00:1b:21:3e:ae:29
igb 0000:09:00.1: eth2: PBA No: e64750-002
igb 0000:09:00.1: Using MSI-X interrupts. 4 rx queue(s), 1 tx queue(s)
ACPI: PCI Interrupt 0000:0a:00.0[A] -> GSI 19 (level, low) -> IRQ 218
PCI: Setting latency timer of device 0000:0a:00.0 to 64
igb 0000:0a:00.0: Intel(R) Gigabit Ethernet Network Connection
igb 0000:0a:00.0: eth3: (PCIe:2.5Gb/s:Width x4) 00:1b:21:3e:ae:2c
igb 0000:0a:00.0: eth3: PBA No: e64750-002
igb 0000:0a:00.0: Using MSI-X interrupts. 4 rx queue(s), 1 tx queue(s)
ACPI: PCI Interrupt 0000:0a:00.1[B] -> GSI 16 (level, low) -> IRQ 177
PCI: Setting latency timer of device 0000:0a:00.1 to 64
igb 0000:0a:00.1: Intel(R) Gigabit Ethernet Network Connection
igb 0000:0a:00.1: eth2: (PCIe:2.5Gb/s:Width x4) 00:1b:21:3e:ae:2d
igb 0000:0a:00.1: eth2: PBA No: e64750-002
igb 0000:0a:00.1: Using MSI-X interrupts. 4 rx queue(s), 1 tx queue(s)

На первый взгляд все замечательно адаптер определился и работает, но смутили надписи 4 rx queue(s), 1 tx queue(s) на каждом из портов. Все дело в том, что у данного адаптера по 8 rx (прием) очередей на каждый порт.

Проверим версию драйвера

modinfo igb


filename: /lib/modules/2.6.18-164.6.1.el5PAE/kernel/drivers/net/igb/igb.ko
version: 1.3.16-k2
license: GPL
description: Intel(R) Gigabit Ethernet Network Driver
author: Intel Corporation,
srcversion: 78555F0A019E05BADBD95AA
alias: pci:v00008086d000010D6sv*sd*bc*sc*i*
alias: pci:v00008086d000010A9sv*sd*bc*sc*i*
alias: pci:v00008086d000010A7sv*sd*bc*sc*i*
alias: pci:v00008086d000010E8sv*sd*bc*sc*i*
alias: pci:v00008086d000010E7sv*sd*bc*sc*i*
alias: pci:v00008086d000010E6sv*sd*bc*sc*i*
alias: pci:v00008086d0000150Asv*sd*bc*sc*i*
alias: pci:v00008086d000010C9sv*sd*bc*sc*i*
depends: 8021q
vermagic: 2.6.18-164.6.1.1.el5PAE SMP mod_unload 686 REGPARM 4KSTACKS gcc-4.1
parm: max_vfs:Maximum number of virtual functions to allocate per physical function (uint)
module_sig: 883f3504af3fe359a79aca2e69819291121b4409f6ecc47545455cf3b51a9aa99f40859e7bd7931a09f76b4b34dde9013eed67638dee172193713aff51f

Очень напрягает практически полное отсутствие секции parm, т.е. драйвер не знает практически никаких параметров.

Поднимем один порт например eth2 и посмотрим как обстоят дела в /proc/interrupts
cat /proc/interrupts|grep eth2

Попытаемся подгрузить драйвер igb с нужными нам параметрами, для того чтобы задействовать по 8 очередей на порт.

modprobe igb IntMode=3,3,3,3 RSS=8,8,8,8


FATAL: Error inserting igb (/lib/modules/2.6.18-164.6.1.1.el5PAE/kernel/drivers/net/igb/igb.ko): Unknown symbol in module, or unknown parameter (see dmesg)

в dmesg

igb: Unknown parameter IntMode'
igb: Unknown parameter
RSS'

опс, драйвер не знает таких параметров 🙁

Надо попробовать свежую версию драйвера igb может с ним нам повезет больше, т. к. собирать драйвер вручную было категорически лень, то вспомнился репозиторий ELREPO в котором данный драйвер присутствует.

Устанавливаем:

rpm -ihv http://elrepo.org/linux/elrepo/el5/i386/RPMS/kmod-igb-PAE-2.0.6-1.el5.elrepo.i686.rpm


modinfo igb

Подгружаем драйвер с нужными параметрами

modprobe igb IntMode=3,3,3,3 RSS=8,8,8,8

Проверяем

cat /proc/interrupts |grep eth2

Теперь на каждый порт мы имеем по 8 очередей.

Победа.

Попытаемся заNAT-ить несколько сот мегабит трафика при штатном драйвере igb и проверим нагрузку на систему.

Для сравнения вспомним данный обзор, в котором процессоры умирали от si (system interrupts) при трафике в 400 мегабит.

«Дунем» через наш адаптер 400 мегабит входящего трафика, исходящий окажется в пределах 300 мегабит.


vnstat -i eth0 -tr

Посмотрим количество conntrack соединений

sysctl -a|grep net.ipv4.netfilter.ip_conntrack_count

Посмотрим нагрузку на ядра

top

Как видим средняя нагрузка на CPU от system interrupts в районе 33% т.е. сервер будет в состоянии занатить 1 гигабит трафика.

http://centos.alt.ru/?p=311

Увеличиваем размер conntrack таблицы в CentOS Linux

Многие системные администраторы сталкивались с проблемой, когда количество сетевых соединений с сервером велико, происходит переполнение conntrack таблицы, из-за чего новые соединения не обрабатываются сервером.

Пример записи в логах указывающих на нехватку количества соединений:

localhost kernel: ip_conntrack: table full, dropping packet.

Увеличить размер conntrack таблицы можно через sysctl.

Размер conntrack таблицы во многих дистрибутивах составляет всего 65536 записей.

В CentOS 5 посмотреть текущее значение можно так:

sysctl -a|grep net.ipv4.netfilter.ip_conntrack_max

Увеличить значение можно через файл /etc/sysctl.conf внеся туда строку:

net.ipv4.netfilter.ip_conntrack_max = НОВОЕ_ЗНАЧЕНИЕ

и заставив систему перечитать изменения:
sysctl -p

Посмотреть сколько в данный момент записей в conntrack таблице можно так:
sysctl -a|grep net.ipv4.netfilter.ip_conntrack_count

В литературе нигде не указываются рекомендованные параметры данной переменной, мои рекомендации следующие:

Если у Вас нет нехватки оперативной памяти на сервере, то установите значение переменой net.ipv4.netfilter.ip_conntrack_max в 1 миллион записей, и отслеживайте значения количества соединений, постепенно уменьшая значение даной переменной до значения (Максимльное количество соединений) +30%.

Будьте осторожны, установив заведомо большое количество соединений при малом количестве оперативной памяти в сервере вы рискуете получить в логах сообщения ядра о нехватке оперативной памяти типа:

localhost kernel: Out of Memory:

и получить в итоге неуправляемую систему.

P.S.В дистрибутивах с новыми ядрами (>2.6.20) параметры задающие максимальное количество записей в conntrack таблице называются
net.netfilter.nf_conntrack_max и net.nf_conntrack_max

Исчерпывающая информация о conntrack находится здесь

http://centos.alt.ru/?p=89