Немного об использовании igb во FreeBSD 8

Некоторое время назад в компании, где я работаю, назрела необходимость обновления пограничного маршрутизатора. Нами был заказан новый мощный сервер, c двумя процессорами Xeon x5650 и сетевыми на базе Intel 82576.

Нехватка nmbclusters

После установки FreeBSD 8.2 и настройки сервера для работы в тестовом стенде, меня постигло разочарование. Простейшая конфигурация: 1 vlan, ospf через quagga, hw.igb.rxd=4096 в /boot/loader.conf — отказывалась работать. Так, например, команда route get висла и не реагировала на ^C. Пинги по влану тоже не ходили. В messages была ругань на igb0: could not setup receive structures. Ругнувшись на очередной сырой релиз FreeBSD, я начал искать решение проблемы.

Изучение netstat -m показало, что в системе не хватает mbuf clusters. Коробочного значения kern.ipc.nmbclusters в 25600 явно не хватало для обслуживания сетевой подсистемы, особенно если учесть, что igb портов у меня 10 — 2 на материнской плате и два навесных квадпорт адаптера. Увеличение значения nmbclusters до 204800 исправило все проблемы, после перезагрузки сеть заработала как надо:

svm# netstat -m
65551/24434/89985 mbufs in use (current/cache/total)
65547/19835/85382/204800 mbuf clusters in use (current/cache/total/max)
65547/19829 mbuf+clusters out of packet secondary zone in use (current/cache)
0/895/895/12800 4k (page size) jumbo clusters in use (current/cache/total/max)
0/0/0/6400 9k jumbo clusters in use (current/cache/total/max)
0/0/0/3200 16k jumbo clusters in use (current/cache/total/max)
147481K/49358K/196840K bytes allocated to network (current/cache/total)
0/0/0 requests for mbufs denied (mbufs/clusters/mbuf+clusters)
0/0/0 requests for jumbo clusters denied (4k/9k/16k)
0/0/0 sfbufs in use (current/peak/max)
0 requests for sfbufs denied
0 requests for sfbufs delayed
0 requests for I/O initiated by sendfile
0 calls to protocol drain routines

Привязка очередей к ядрам процессора

Драйвер igb поступает следующим образом: прерывание первой очереди любого из сетевых адаптеров привязывается к первому ядру, прерывание второй очереди — ко второму ядру, и т.д для всех очередей. В конечном итоге может возникнуть такая ситуация, что при 100% загрузке любого из ядер — начнут страдать очереди всех адаптеров, привязанные к этому ядру. Для того, чтобы этого избежать, следует переназначить привязку прерываний к ядрам процессора. Я, к примеру, делаю так:

igb_cpu.sh

#!/bin/sh
basedir=$(dirname $0)
for l in `cat ${basedir}/igb_cpu.txt`; do
    if [ -n "$l" ]; then
        iface=`echo $l | cut -f 1 -d ":"`
        queue=`echo $l | cut -f 2 -d ":"`
        cpu=`echo $l | cut -f 3 -d ":"`
        irq=`vmstat -i | grep "${iface}:que ${queue}" | cut -f 1 -d ":" | sed "s/irq//g`
        echo "Binding ${iface} queue #${queue} (irq ${irq}) -> CPU${cpu}"
        cpuset -l $cpu -x $irq
    fi
done

igb_cpu.txt

svm# cat igb_cpu.txt
igb7:0:12
igb7:1:13
igb7:2:14
igb7:3:15
igb8:0:16
igb8:1:17
igb8:2:18
igb8:3:19
igb9:0:20
igb9:1:21
igb9:2:22
igb9:3:23

Использование:

svm# ./igb_cpu.sh
Binding igb7 queue #0 (irq 291) -> CPU12
Binding igb7 queue #1 (irq 292) -> CPU13
Binding igb7 queue #2 (irq 293) -> CPU14
Binding igb7 queue #3 (irq 294) -> CPU15
Binding igb8 queue #0 (irq 296) -> CPU16
Binding igb8 queue #1 (irq 297) -> CPU17
Binding igb8 queue #2 (irq 298) -> CPU18
Binding igb8 queue #3 (irq 299) -> CPU19
Binding igb9 queue #0 (irq 301) -> CPU20
Binding igb9 queue #1 (irq 302) -> CPU21
Binding igb9 queue #2 (irq 303) -> CPU22
Binding igb9 queue #3 (irq 304) -> CPU23

Локи в ipfw nat

При вводе сервера в боевой режим я заплакал кровавыми слезами. Производительность оказалась в разы хуже, чем ожидалось. Процессор начал отжираться практически полностью:

   12 root       88 -48    -     0K  1408K WAIT    0  47.7H 683.11% intr
    0 root      256  -8    0     0K  4080K -       2 550:06 567.72% kernel

И это при скромных 300 мегабитах/c внешки и 200 мегабитах/c пиринга. В ipfw кроме скромного ipfw nat никакой обработки пакетов не происходило. С помощью Вадима Гончарова удалось быстро локализовать проблему. Как оказалось, она была в единственном инстансе ната: «То есть, несколько тредов одновременно постоянно дерутся за доступ к instance ната — оно не параллелится. Решение: натить в несколько внешних IP-адресов, для каждого заводить отдельный инстанс libalias (ipfw nat).»

Добавление второго инстанса ната в разы снизило нагрузку на процессор. Итоговый idle в пики нагрузки держался на уровне 85%, что наконец стало соответствовать ожиданиям.

Итоговая конфигурация

CPU:

Timecounter "i8254" frequency 1193182 Hz quality 0
CPU: Intel(R) Xeon(R) CPU           X5650  @ 2.67GHz (2677.44-MHz K8-class CPU)
  Origin = "GenuineIntel"  Id = 0x206c2  Family = 6  Model = 2c  Stepping = 2
  Features=0xbfebfbff
  Features2=0x9ee3fd
  AMD Features=0x2c100800
  AMD Features2=0x1
  TSC: P-state invariant
real memory  = 12889096192 (12292 MB)
avail memory = 12370157568 (11797 MB)
ACPI APIC Table: <112510 APIC1400>
FreeBSD/SMP: Multiprocessor System Detected: 24 CPUs
FreeBSD/SMP: 2 package(s) x 6 core(s) x 2 SMT threads

Сетевые адаптеры:

igb0:  port 0xac00-0xac1f mem 0xfbde0000-0xfbdfffff,0xfbdc0000-0xfbddffff,0xfbd9c000-0xfbd9ffff irq 28 at device 0.0 on pci1
igb0: Using MSIX interrupts with 5 vectors
igb0: [ITHREAD]
igb0: [ITHREAD]
igb0: [ITHREAD]
igb0: [ITHREAD]
igb0: [ITHREAD]

/boot/loader.conf

hw.igb.rxd=4096
hw.igb.txd=4096
hw.igb.num_queues=4

/etc/sysctl.conf

net.inet.flowtable.enable=0
net.inet.ip.fw.one_pass=0
net.inet.udp.blackhole=1
net.inet.tcp.blackhole=2
net.inet.ip.intr_queue_maxlen=4096
net.inet.ip.fastforwarding=0
net.inet.tcp.drop_synfin=1

kern.maxfiles=204800
kern.maxfilesperproc=200000
kern.ipc.maxsockets=204800

net.route.netisr_maxqlen=4096
kern.ipc.nmbclusters=204800

dev.igb.0.rx_processing_limit=-1
dev.igb.1.rx_processing_limit=-1
dev.igb.2.rx_processing_limit=-1
dev.igb.3.rx_processing_limit=-1
dev.igb.4.rx_processing_limit=-1
dev.igb.5.rx_processing_limit=-1
dev.igb.6.rx_processing_limit=-1
dev.igb.7.rx_processing_limit=-1
dev.igb.8.rx_processing_limit=-1
dev.igb.9.rx_processing_limit=-1

netstat 1

            input        (Total)           output
   packets  errs idrops      bytes    packets  errs      bytes colls
    206603     0     0  161112077     203476     0  160991329     0
    208062     0     0  159346760     204878     0  159324930     0
    206858     0     0  158731344     203725     0  158685545     0
    206437     0     0  159348096     203246     0  159198474     0
    214769     0     0  166807617     211617     0  166737724     0

top -SIP

last pid: 35640;  load averages:  0.14,  0.10,  0.08           up 1+23:59:09  12:23:22
477 processes: 25 running, 364 sleeping, 88 waiting
CPU 0:   0.0% user,  0.0% nice,  3.0% system,  0.0% interrupt, 97.0% idle
CPU 1:   0.0% user,  0.0% nice,  0.0% system,  0.0% interrupt,  100% idle
CPU 2:   0.0% user,  0.0% nice,  1.5% system,  0.0% interrupt, 98.5% idle
CPU 3:   0.0% user,  0.0% nice,  0.0% system,  0.0% interrupt,  100% idle
CPU 4:   0.0% user,  0.0% nice,  1.5% system,  0.0% interrupt, 98.5% idle
CPU 5:   0.0% user,  0.0% nice,  1.5% system,  0.0% interrupt, 98.5% idle
CPU 6:   0.0% user,  0.0% nice,  1.5% system,  0.0% interrupt, 98.5% idle
CPU 7:   0.0% user,  0.0% nice,  1.5% system,  0.0% interrupt, 98.5% idle
CPU 8:   0.0% user,  0.0% nice,  3.0% system,  0.0% interrupt, 97.0% idle
CPU 9:   0.0% user,  0.0% nice,  0.0% system,  0.0% interrupt,  100% idle
CPU 10:  0.0% user,  0.0% nice,  1.5% system,  0.0% interrupt, 98.5% idle
CPU 11:  0.0% user,  0.0% nice,  0.0% system,  0.0% interrupt,  100% idle
CPU 12:  0.0% user,  0.0% nice,  0.0% system, 29.9% interrupt, 70.1% idle
CPU 13:  0.0% user,  0.0% nice,  0.0% system, 14.9% interrupt, 85.1% idle
CPU 14:  0.0% user,  0.0% nice,  0.0% system, 22.4% interrupt, 77.6% idle
CPU 15:  0.0% user,  0.0% nice,  0.0% system, 22.4% interrupt, 77.6% idle
CPU 16:  0.0% user,  0.0% nice,  0.0% system,  1.5% interrupt, 98.5% idle
CPU 17:  0.0% user,  0.0% nice,  0.0% system,  4.4% interrupt, 95.6% idle
CPU 18:  0.0% user,  0.0% nice,  0.0% system,  4.4% interrupt, 95.6% idle
CPU 19:  0.0% user,  0.0% nice,  0.0% system,  7.4% interrupt, 92.6% idle
CPU 20:  0.0% user,  0.0% nice,  0.0% system, 22.1% interrupt, 77.9% idle
CPU 21:  0.0% user,  0.0% nice,  0.0% system, 20.6% interrupt, 79.4% idle
CPU 22:  0.0% user,  0.0% nice,  0.0% system, 16.2% interrupt, 83.8% idle
CPU 23:  0.0% user,  0.0% nice,  0.0% system, 17.6% interrupt, 82.4% idle
Mem: 62M Active, 14M Inact, 1629M Wired, 132K Cache, 10G Free
Swap: 12G Total, 12G Free

  PID USERNAME  THR PRI NICE   SIZE    RES STATE   C   TIME   WCPU COMMAND
   11 root       24 171 ki31     0K   384K RUN     0 1055.8 2205.62% idle
   12 root       88 -68    -     0K  1408K WAIT   23  78.1H 227.49% intr
    0 root      257 -68    0     0K  4096K -       3 691:10  4.10% kernel

Немного об использовании igb во FreeBSD 8: 11 комментариев

  1. зря Вы так, человек сделал заметку для себя, а заодно и поделился своим опытом.
    Например мне интересен его опыт. Взял себе на заметку.
    Критика — всегда хорошо, когда она конструктивная!

  2. есть проблема (может кто сталкивался)
    четырехпортовый Intel, FreeBSD 8.2
    Intel(R) PRO/1000 Network Connection version — 2.0.7
    igb0 и igb3 работают прекрасно
    igb1 и igb2 — тишина, ну т.е. status:active, но tcpdump кажет мертвую тишину
    я точно уверен, что проблема не в карте.
    эксперименты проводить на машине нет возможности никакой (надо было ядро пересобрать — перегрузки прошлый раз ждал 3 месяца, пока позволили)

      1. ХТ не более чем маркетинговый высер. В случае работы сетевой части в фрибсд ( прерывания ) он только всё усугубляет ( также как и при работе виртуалок ).
        Усугубляет на столько что при отключении его наблюдается прирост производительности в случае работы ипфщ/думминет в 1.3-2х раза
        Я не инженер но могу предположить что обработка и/о прерываний логическим ( виртуальным / не существующим ) ядром не есть хорошо — несколько ядер пытаются делить между собой фактически одно ядро и это перетягивание является губительным для обшей производительности системы

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *