Управление ядрами ЦПУ при обработке сетевого трафика

от автора

Привет, Хабр! Не так давно столкнулся с задачей разработки альтернативного решения для ограничения сетевого трафика. Такая задача возникла в рамках разработки системы лицензирования для продукта класса NGFW (Next Generation Firewall). Используя такую систему ограничений можно было бы предусмотреть несколько видов лицензий на коммерческое использование продукта, где в зависимости от уровня приобретенной лицензии можно было бы предоставлять полную, либо урезанную функциональность продукта в части его производительности. В этой статье хочу поделиться опытом решения данной задачи.

Типичные средства ограничения сетевого трафика

Как известно, существует несколько подходов к ограничению трафика:

  • Стандартные утилиты командной строки, типа tc;

  • Решения на основе специальных правил в iptables, или nftables;

  • Rate limiters на стороне веб-сервера;

  • Ограничения на ресурсы в Docker и k8s.

Можно было бы остановиться на одном из перечисленных выше решений и завершить на этом статью, но в каждом из этих подходов были свои недостатки, не позволяющие в полной мере удовлетворить требования, предъявляемые к нашей системе ограничения трафика.

Основные требования:

  1. Скрытность для пользователя имеющего root права на сервере где все это работает;

  2. Перенастройка ограничителя «на лету», т.е. мгновенно и в любой момент без необходимости перезагрузки, или какой-то другой долгой перенастройки всей системы;

  3. Не влиять на процессы системы, не связанные с обработкой сетевого трафика.

Одним из главных требований (п.1) было максимально затруднить обход ограничений для пользователя получившего root права. Второй пункт требований говорит о максимальной оперативности и быстродействии при изменении политики ограничения. Третий пункт означает, что работа нашего ограничителя не должна ухудшать производительность остальных процессов системы, не связанных с обработкой сетевого трафика.

Таким образом, применение утилиты типа tc не будет удовлетворять п.1 — любой администратор, или сетевой инженер может спокойно поменять выставленные настройки в tc и обойти ограничение. Решения на основе iptables и nftables не удовлетворяют требованиям из п.1 и п.2. Поскольку правила iptables могут быть многочисленными, то изменения рейт лимитеров в них может приводить к перенастройке огромного числа правил, что негативно влияет на оперативность и производительность системы в целом. Два оставшихся варианта на основе докеров, k8s и веб-сервера не подходят из-за невозможности или сложности интеграции целевого продукта с ними.

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

Постановка задачи

Разработать средство ограничения числа используемых ядер процессора при обработке сетевого трафика.

Ограничение числа ядер, в идеале, так же должно:

  1. Применяться для всех подсистем ядра Linux, занятых обработкой сетевого трафика (прием от сетевой карты, маршрутизация, iptables и т.п.);

  2. Не влиять на процессы ядра Linux, не связанные с обработкой сетевого трафика, а также не влиять на какие-либо приложения — для всего этого продолжают использоваться все доступные процессорные ядра;

  3. Допускать перенастройку «на лету» в любой момент времени.

Решение с использованием ethtool

Продвинутые сетевые карты позволяют производить гибкую настройку своих параметров с использованием утилиты ethtool. Такие карты используют DMA для записи данных напрямую в память, откуда операционная система может их извлечь для последующей обработки. Устройства, поддерживающие механизм RSS (Receive Side Scaling), могут одновременно писать входящие пакеты в несколько разных областей памяти, каждая из которых, представляет отдельную очередь. Это позволяет ОС использовать несколько ядер CPU для параллельной обработки данных из этих очередей. Таким образом, имея возможность ограничения количества приемных очередей производится и ограничение на количество ядер ЦПУ, привязанных к конкретной очереди, и обрабатывающих пакеты из этих очередей. С помощью утилиты ethtool можно настраивать количество и размер очередей приёма. Изменение этих параметров позволяет существенно повлиять на отношение обработанных и отброшенных пакетов.

Схема испытаний

Рисунок 1 - Схема испытаний

Рисунок 1 — Схема испытаний

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

  1. Хост с ОС Centos7.9 и ядром Linux версии 3.10;

  2. Сетевая карта Mellanox MT27800 (100Гб/с) с драйвером mlx5_core версии 5.7-1.0.2;

  3. Утилита ethtool версии 4.8;

  4. Генератор тестового трафика T-Rex.

Выбор ОС и сетевой карты были продиктованы требованиями к эксплуатации конечного продукта.
Генератор трафика T-Rex размещался на отдельном хосте с аналогичными характеристиками.
Как уже отмечалось, сетевые карты, поддерживающие RSS обычно позволяют настраивать количество очередей приёма (каналов приёма, RX-channels):

Как можно видеть, сетевая карта поддерживает до 40 очередей (по количеству ядер процессора).

Апробация

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

Порядок проведения тестов:

  1. Установка числа очередей с помощью ethtool (Например, ethtool -L eth3 combined 10);

  2. Запуск нагрузочного трафика с помощью t-rex;

  3. Снятие статистики работы сетевого стека и системы на разных уровнях спустя примерно один и тот же интервал времени генерации трафика.

В качестве наблюдаемых параметров системы рассматривались значения следующих ресурсов ОС:

  • Счетчики аппаратных прерываний из /proc/interrupts;

  • Счетчики softirq из /proc/softirqs;

  • Число принятых и отброшенных пакетов из /proc/net/dev;

  • Нагрузки на процессор используя mpstat и top.

Далее приводятся результаты тестирования для различных значений количества очередей приема Nq=1, 4, 10, 40.

1. Число очередей Nq = 1.
В этом случае имеем максимальное ограничение.
Установка значений для интерфейсов eth3, eth4 с помощью ethtool:

ethtool -L eth3 combined 1 ethtool -L eth4 combined 1
 Рисунок 2 - Число прерываний interrupts и softirq при Nq = 1

Рисунок 2 — Число прерываний interrupts и softirq при Nq = 1

Как видно из рисунка 2, после запуска генерации трафика, значения счетчиков прерываний начинают увеличиваться. В данном случае можно видеть, что трафик для интерфейса eth3 обрабатывается с помощью ядер CPU39, а для eth4 с помощью CPU10. Здесь номер столбца в выводе /proc/interrupts является номером ядра ЦПУ в пределах от 0 до 39. Значения счетчиков softirqs так же растет для задействованных ядер.

 Рисунок 3 - Нагрузка на ЦПУ при Nq = 1

Рисунок 3 — Нагрузка на ЦПУ при Nq = 1

Из рисунка 3. можно так же видеть, что увеличивается нагрузка на задействованные ядра ЦПУ CPU10 и CPU39.

 Рисунок 4 - Число принятых/отброшенных пакетов при Nq = 1

Рисунок 4 — Число принятых/отброшенных пакетов при Nq = 1

На рисунке 4 видно, что растет число отброшенных пакетов, а обработка потоков softirq происходит на ядрах CPU10 и CPU39.

Показания t-rex при генерации трафика
 Рисунок 5 - Показание t-rex при генерации трафика при Nq = 1

Рисунок 5 — Показание t-rex при генерации трафика при Nq = 1

Далее представлены показания при числе очередей Nq = 4, 10 и 40 для интерфейса eth4 (для eth3 показания будут аналогичными)

2. Число установленных очередей Nq = 4
ethtool -L eth3 combined 4 ethtool -L eth4 combined 4
 Рисунок 6 - Число прерываний interrupts и softirq при Nq = 4

Рисунок 6 — Число прерываний interrupts и softirq при Nq = 4
 Рисунок 7 - Нагрузка на ЦПУ при Nq = 4

Рисунок 7 — Нагрузка на ЦПУ при Nq = 4
 Рисунок 8 - Число принятых/отброшенных пакетов при Nq = 4

Рисунок 8 — Число принятых/отброшенных пакетов при Nq = 4
3. Число установленных очередей Nq = 10
ethtool -L eth3 combined 10 ethtool -L eth4 combined 10
 Рисунок 9 - Число прерываний interrupts и softirq при Nq = 10

Рисунок 9 — Число прерываний interrupts и softirq при Nq = 10
 Рисунок 10 - Нагрузка на ЦПУ при Nq = 10

Рисунок 10 — Нагрузка на ЦПУ при Nq = 10
 Рисунок 11 - Число принятых/отброшенных пакетов при Nq = 10

Рисунок 11 — Число принятых/отброшенных пакетов при Nq = 10
4. Число установленных очередей Nq = 40
ethtool -L eth3 combined 40 ethtool -L eth4 combined 40
Рисунок 12.a - Число прерываний interrupts для Nq = 40

Рисунок 12.a — Число прерываний interrupts для Nq = 40
 Рисунок 12.b - Число прерываний softirq для Nq = 40

Рисунок 12.b — Число прерываний softirq для Nq = 40
 Рисунок 13 - Нагрузка на ЦПУ при Nq = 40

Рисунок 13 — Нагрузка на ЦПУ при Nq = 40
 Рисунок 14 - Число принятых/отброшенных пакетов при Nq = 40

Рисунок 14 — Число принятых/отброшенных пакетов при Nq = 40
 Рисунок 15 - Нагрузка на ЦПУ при Nq = 40

Рисунок 15 — Нагрузка на ЦПУ при Nq = 40

Исходя из представленных результатов можно проследить некоторые тенденции:

  1. При увеличении числа очередей снижается нагрузка на ЦПУ за счет пропорционального увеличения числа ядер, участвующих в процессе обработки трафика (Рисунки 3, 4, 7, 8, 10, 11, 13, 15);

  2. При увеличении числа очередей снижается доля отброшенных пакетов по тем же причинам, что и в п.1 (Рисунки 4, 8, 10, 11, 14)

Выводы

  1. Число очередей обработки пакетов соответствует числу задействованных при этом ядер процессора, где каждая очередь привязана к своему ядру процессора;

  2. Количество заданных очередей напрямую влияет на общую загрузку системы при обработке пакетов;

  3. Сетевые карты, поддерживающие управление с помощью ethtool и поддерживающие RSS позволяют настраивать количество и размер очередей приёма, что напрямую влияет на отношение обработанных и отброшенных пакетов при нагруженном трафике.

Таким образом, уменьшая число очередей обработки пакетов, уменьшается и число ядер ЦПУ, участвующих в обработке сетевого трафика, что ведет к увеличению доли отбрасываемых пакетов и ухудшению пропускной способности канала. Разумеется, подобное влияние лучше всего будет заметно при высокой нагрузке — свыше 1 Gb/s, и мало применимо в не нагруженных системах. Тем не менее, рассмотренный подход может быть использован, как одно из возможных решений для ограничения трафика в высоконагруженных системах.

Что касается одного из требований скрытности для пользователя с root правами, то конечно, как и при использовании утилиты tc, продвинутый пользователь может так же перенастроить сетевой стек с помощью ethtool и обойти ограничение, но кажется, для этого понадобилась бы чуть большая экспертиза, чем для использования tc.


ссылка на оригинал статьи https://habr.com/ru/articles/857986/


Комментарии

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

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