Всем привет!
В этой статье я хочу рассказать вам про одну полезную фичу, которая есть в сетевой карте Intel 82599.
Речь пойдёт об аппаратном ограничении скорости выходного потока пакетов.
К сожалению, она не доступна в линуксе «из коробки» и требуются некоторые усилия, чтобы её задействовать.
Кому интересно — добро пожаловать под кат.
Началось всё с того, что на днях мы тестировали оборудование, которое занимается фильтрацией трафика.
Девайс MX — это DPI-устройство. Оно разбирает пакет, поступающий из 10G и отправляет его на гигабитный порт, если он попадает под заданный критерий (адреса, порты и прочее). На стороне PC — карта Intel 82599 с драйвером ixgbe. Трафик генерировали при помощи tcpreplay, а собирали при помощи tcpdump. Дамп с тестовым трафиком у нас был (дано по условиям задачи).
Поскольку в общем случае отфильтровать 10G и отослать результат в 1G не представляется возможным (скорости-то разные, а буферы не резиновые), нам пришлось ограничивать скорость генерации пакетов. Тут важно сказать, что мы проводили не нагрузочное тестирование, а функциональное, поэтому нагрузка на 10G была не очень важна и влияла только на длительность теста.
Казалось бы, задача решается просто: открываем man tcpreplay и видим там ключик -M.
Запускаем:
$ sudo tcpreplay -M10 -i eth3 dump.cap
В результате в статистике MX'а появляется следующее:
| Name | Packets | Bytes | Overflow pkt |
| EX1 to EG1| 626395| 401276853| 53|
| EX1 to EG2| 0| 0| 0|
| EX1 RX| 19426782| 4030345892| 0|
Столбец overflow pkt означает, что часть пакетов не «влезла» в 1G, т.к. выходной буфер переполнился. А это значит, что до PC не дошло 53 пакета. А они нам очень нужны, ведь мы проверяем правильность функционирования фильтров.
Получается, что сетевая карта 82599 создаёт burst'ы независимо от того, какая скорость выставлена в tcpreplay.
Встал вопрос о том, как можно контролировать нагрузку в 10G на уровне, максимально приближенном к линку. И тут нам в голову пришла мысль, что карта это уже умеет. Так и есть! В datasheet'e нашли подтверждение в разделе 1.4.2 Transmit Rate Limiting. Осталось только научиться этой функцией управлять.
Рычагов для этого (нужных файликов в sysfs) в нашем ядре мы не нашли (мы игрались c 3.2, debian). Порылись в сорцах свежего ядра (3.14) и там тоже не нашли.
Оказалось, что на github'е уже есть проект, который называется tx-rate-limits.
Дальше всё тривиально :) Собрали ядро, поставили на систему:
$ git checkout https://github.com/jrfastab/tx-rate-limits.git
$ cd tx-rate-limits
$ fakeroot make-kpkg --initrd -j 8 kernel-image
$ sudo dpkg -i ../linux-image-3.6.0-rc2+_3.6.0-rc2+-10.00.Custom_amd64.deb
Перезагрузились, и… в sysfs теперь есть файлики для управления нагрузкой передачи!
$ ls /sys/class/net/eth5/queues/tx-0/
byte_queue_limits tx_rate_limit tx_timeout xps_cpus
Дальше записываем в tx_rate_limit требуемое значение в мегабитах:
# RATE=100
# for n in `seq 0 7`; do echo $RATE > /sys/class/net/eth4/queues/tx-$n/tx_rate_limit ; done
В итоге в статистике MX'а видим, что overflow не происходит, т.к. скорость контролируется картой и burst'ов больше нет, весь отфильтрованный трафик попадает в 1G без потерь:
| Name | Packets | Bytes | Overflow pkt |
| EX1 to EG1| 22922532| 14682812077| 0|
| EX1 to EG2| 0| 0| 0|
| EX1 RX| 713312575| 147948837844| 0|
Возможно, для решения данной задачи есть более простой способ.
Буду очень благодарен, если кто-нибудь поделится.
Автор: paulig