Немного поэкспериментировал с
netmap.
На свежем current в целом работает.
Железо:
- CPU: Intel Core i3-550
- NIC: Intel 82599EB, с двумя SFP+ модулями. поскольку 10G коммутатора или другого ящика с 10G под рукой не было, то соединил патчкордами два модуля на одной карточке.
- MB: MSI H55M-P31
В 8-ке netmap не заработал, поэтому на всякий случай обновился сразу до HEAD.
Ядро отличается от GENERIC наличием опции
device netmap
и отключенным WITNESS (который заметно влияет на производительность).
В /etc/sysctl.conf добавил
hw.intr_storm_threshold=15000
на 10G и маленьких пакетах прерываний получается много - ядро думает что случился interrupt storm и начинает фильтровать прерывания (в тестах ).
В /boot/loader.conf небольшой тюнинг
hw.ixgbe.num_queues=2 # 2 real cores on CPU
hw.ixgbe.rx_process_limit=512
hw.ixgbe.tx_process_limit=512
hw.ixgbe.txd=2048
hw.ixgbe.rxd=2048
но на результаты данного теста это влияет не очень сильно.
В /usr/src/tools есть тестовые приложения. Проще всего использовать pkt-gen, который может работать как генератор или получатель пакетов.
# cd /usr/src/tools/tools/netmap
# make
В одной консоли можно запустить
./pkt-gen -i ix1 -f rx -p 2 -c 4 -w 5 для приема пакетов.
В другой
./pkt-gen -p 2 -i ix0 -f tx -n 9500000 -l 64 -s 192.168.1.1:12345 -d 192.168.1.201-192.168.1.249:12345 -D 00:25:90:64:3b:3f -S 00:25:90:64:3b:3e -w 5
Поскольку netmap переводит карточку в специальный режим (и отключает её от сетевого стека), для ssh нужна еще одна сетевая карточка, работающая без netmap.
Использование диапазона IP нужно чтобы обеспечить более равномерное распределение пакетов по RX очередям. Насколько понимаю очередь для входящих пакетов выбирается на основании хэша ряда заголовков включая src-ip и dst-ip. В моем случае очереди две, потоков на передающем pkt-gen может быть тоже максимум две. Каждый поток один раз создает пакет и потом много раз его отправляет. Так что используются только два разных dst ip. Чтобы была равномерная загрузка очередей пару раз запускал с разными ip и смотрел в systat -vmstat чтобы прерывания на всех очередях (ix1:queue*).
На реальной нагрузке как правило много разных пакетов с разными ip и распределение по очередями получается равномерное.
На больших пакетах выглядит так:
CPU: 1.0% user, 0.0% nice, 20.1% system, 11.4% interrupt, 67.5% idle
Mem: 47M Active, 35M Inact, 792M Wired, 42M Buf, 6861M Free
Swap: 2048M Total, 2048M Free
PID USERNAME PRI NICE SIZE RES STATE C TIME WCPU COMMAND
2309 citrin 52 0 348M 2224K select 1 0:32 38.96% ./pkt-gen -i ix1 -f rx -p 2 -c 4 -w 5{pkt-gen}
2309 citrin 52 0 348M 2224K select 3 0:30 38.38% ./pkt-gen -i ix1 -f rx -p 2 -c 4 -w 5{pkt-gen}
12 root -92 - 0K 368K WAIT 1 5:18 14.45% [intr{irq268: ix1:que }]
12 root -92 - 0K 368K WAIT 0 1:43 12.99% [intr{irq267: ix1:que }]
12 root -92 - 0K 368K WAIT 1 1:50 7.57% [intr{irq265: ix0:que }]
2318 citrin 21 0 348M 10452K select 2 0:02 1.56% ./pkt-gen -p 2 -i ix0 -f tx -n 95000000 -l 1450
2318 citrin 21 0 348M 10452K select 2 0:02 1.37% ./pkt-gen -p 2 -i ix0 -f tx -n 95000000 -l 1450
12 root -92 - 0K 368K WAIT 0 0:35 0.29% [intr{irq264: ix0:que }]
0 root -16 0 0K 240K sched 2 0:44 0.00% [kernel{swapper}]
12 root -60 - 0K 368K WAIT 0 0:12 0.00% [intr{swi4: clock}]
Результат:
Sent 95000000 packets, 1450 bytes each, in 112.04 seconds.
Speed: 847.91 Kpps Bandwidth: 9.84 Gbps (raw 10.00 Gbps)
Received 95000000 packets, in 112.05 seconds.
На маленьких пакетах тоже можно забить канал полностью:
CPU: 5.0% user, 0.0% nice, 60.3% system, 9.5% interrupt, 25.2% idle
Mem: 48M Active, 35M Inact, 793M Wired, 42M Buf, 6860M Free
Swap: 2048M Total, 2048M Free
PID USERNAME PRI NICE SIZE RES STATE C TIME WCPU COMMAND
2728 citrin 100 0 348M 2224K CPU2 2 0:38 96.19% ./pkt-gen -i ix1 -f rx -p 2 -c 4 -w 5{pkt-gen}
2728 citrin -92 0 348M 2224K CPU1 1 0:37 93.90% ./pkt-gen -i ix1 -f rx -p 2 -c 4 -w 5{pkt-gen}
2737 citrin 52 0 348M 10452K select 3 0:18 42.68% ./pkt-gen -p 2 -i ix0 -f tx -n 950000000 -l 64
2737 citrin 85 0 348M 10452K CPU2 2 0:18 41.70% ./pkt-gen -p 2 -i ix0 -f tx -n 950000000 -l 64
12 root -92 - 0K 368K WAIT 1 2:26 9.57% [intr{irq265: ix0:que }]
12 root -92 - 0K 368K RUN 0 0:47 6.88% [intr{irq264: ix0:que }]
12 root -92 - 0K 368K RUN 0 4:46 6.40% [intr{irq267: ix1:que }]
12 root -92 - 0K 368K WAIT 1 5:27 6.05% [intr{irq268: ix1:que }]
0 root -92 0 0K 240K - 3 3:19 0.00% [kernel{ix1 que}]
0 root -16 0 0K 240K sched 3 0:44 0.00% [kernel{swapper}]
Результат:
Sent 950000000 packets, 64 bytes each, in 66.89 seconds.
Speed: 14.20 Mpps Bandwidth: 7.27 Gbps (raw 10.00 Gbps)
Received 935736383 packets, in 66.94 seconds.
Для сравнения тест с использованием libpcap/bpf - ./pkt-gen -i ixN -P (на принимающем интерфейсе сделал ifconfig monitor)
CPU: 1.9% user, 0.0% nice, 48.3% system, 35.5% interrupt, 14.3% idle
Mem: 55M Active, 172M Inact, 1101M Wired, 807M Buf, 6408M Free
Swap: 2048M Total, 2048M Free
PID USERNAME PRI NICE SIZE RES STATE C TIME WCPU COMMAND
4654 root 99 0 21068K 2268K CPU2 2 0:25 88.87% ./pkt-gen -p 2 -i ix0 -f tx -n 95000000 -l 1450
4654 root 99 0 21068K 2268K RUN 3 0:25 88.28% ./pkt-gen -p 2 -i ix0 -f tx -n 95000000 -l 1450
12 root -92 - 0K 368K WAIT 1 7:43 46.48% [intr{irq268: ix1:que }]
12 root -92 - 0K 368K WAIT 0 5:30 46.39% [intr{irq267: ix1:que }]
0 root -92 0 0K 240K - 3 0:21 6.49% [kernel{ix0 que}]
0 root -92 0 0K 240K - 2 0:10 6.49% [kernel{ix0 que}]
12 root -92 - 0K 368K WAIT 1 2:46 5.86% [intr{irq265: ix0:que }]
12 root -92 - 0K 368K WAIT 0 1:01 5.86% [intr{irq264: ix0:que }]
995 citrin 21 0 21108K 4224K select 3 1:12 1.27% systat -vmstat
0 root -92 0 0K 240K - 3 0:05 0.10% [kernel{ix1 que}]
0 root -92 0 0K 240K - 3 3:23 0.00% [kernel{ix1 que}]
12 root -60 - 0K 368K WAIT 2 1:13 0.00% [intr{swi4: clock}]
Sent 95000000 packets, 1450 bytes each, in 148.89 seconds.
Speed: 638.04 Kpps Bandwidth: 7.40 Gbps (raw 7.52 Gbps)
и pcap/bpf на маленьких:
CPU: 2.6% user, 0.0% nice, 65.6% system, 5.5% interrupt, 26.3% idle
Mem: 57M Active, 172M Inact, 1103M Wired, 807M Buf, 6404M Free
Swap: 2048M Total, 2048M Free
PID USERNAME PRI NICE SIZE RES STATE C TIME WCPU COMMAND
4705 root 92 0 21068K 2268K RUN 2 0:12 69.38% ./pkt-gen -p 2 -i ix0 -f tx -n 95000000 -l 64
4705 root 92 0 21068K 2268K CPU0 0 0:12 69.38% ./pkt-gen -p 2 -i ix0 -f tx -n 95000000 -l 64
0 root -92 0 0K 240K - 3 6:28 32.86% [kernel{ix0 que}]
0 root -92 0 0K 240K CPU3 3 6:34 31.88% [kernel{ix0 que}]
12 root -92 - 0K 368K WAIT 1 12:05 12.60% [intr{irq268: ix1:que }]
12 root -92 - 0K 368K RUN 0 9:46 11.96% [intr{irq267: ix1:que }]
0 root -92 0 0K 240K - 3 0:49 3.56% [kernel{ix1 que}]
0 root -92 0 0K 240K - 2 4:07 3.27% [kernel{ix1 que}]
12 root -92 - 0K 368K WAIT 1 3:40 2.88% [intr{irq265: ix0:que }]
12 root -92 - 0K 368K RUN 0 1:52 2.59% [intr{irq264: ix0:que }]
Sent 95000000 packets, 64 bytes each, in 96.74 seconds.
Speed: 982.03 Kpps Bandwidth: 502.80 Mbps (raw 691.35 Mbps)
Из неприятного:
Довольно часто после запуска pkt-gen одна из карт теряет линк. Чаще всего при запуске pkt-gen -i ix1 -f rx пропадает линк на ix0. Помогает ifconfig down/up. Скорее всего это особенность комбинации netmap+ixgbe, кода тестировал на re проблем с линком не было. Впрочем от этого не сильно легче - для highload нужна карточка ixgbe. Надеюсь что при подключении к коммутатору, а не другой карточке линк теряться не будет.
В целом производительность впечатляет, особенно на мелких пакетах, которые тоже встречаются в интернете.