Для Новичков Об Управлении Шириной Канала В Linux

Некоторое время назад меня попросили настроить простую балансировку трафика в удаленном филиале.

Работают они, бедняги, через ADSL, а отправка больших объемов писем (сканов документов) забивает у них весь обратный канал, что приводит к проблемам в работе с онлайн-офисными программами через VPN. В качестве шлюза они используют Linux (Fedora).

До этого я пару раз видел, как подобная балансировка настраивалась через ipfw на FreeBSD, и так как механизм iptables я знаю достаточно хорошо, особых проблем не ожидал.

Но покопавшись в интернете, я был неприятно удивлён, что iptables мне здесь совершенно не поможет. И знания о порядке прохождения пакетов через его таблицы и правила мне мало пригодятся.

Вам нужно изучить tc из пакета iproute2. Неожиданно для себя я потратил два дня более-менее на то, чтобы разобраться в балансировке трафика с помощью iproute2. Сначала мне попалась не самая лучшая для новичка статья про ХТБ( Здесь ).

Различные примеры из Интернета также иногда приводили в замешательство, поскольку зачастую не описывали ни конкретные опции, ни смысл их использования.

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

Сразу оговорюсь: «резать» мы будем только трафик, исходящий из сетевого интерфейса.

Входящий тоже можно отрегулировать, но для этого нужны дополнительные хитрости.



Бесклассовые дисциплины

Итак, в Linux для управления трафиком каждому сетевому интерфейсу назначается дисциплина (qdisc) .

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

Но вам не следует бояться; по сути, дисциплина — это всего лишь алгоритм обработки очереди сетевых пакетов.

На одном интерфейсе можно использовать несколько дисциплин, а так называемый корневая дисциплина (корневой qdisc) .

При этом каждый интерфейс имеет свою корневую дисциплину.



prio_fast
По умолчанию после загрузки системы root qdisc устанавливает алгоритм обработки пакетов типа pfifo_fast .



Для новичков об управлении шириной канала в Linux

Мы проверяем: # tc qdisc qdisc pfifo_fast 0: корневые группы dev eth0 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1 pfifo_fast — это обычный алгоритм «Первый ввод — Первый вывод», но с некоторой приоритизацией трафика.

Дисциплина этого типа содержит три очереди FIFO с разными приоритетами обработки пакетов.

Пакеты сортируются на основе флага ToS (тип услуги) в каждом IP-пакете.

Пакет в FIFO0 имеет наивысший приоритет обработки, а в FIFO2 — наименьший.

Сам ToS требует отдельного разговора, поэтому предлагаю ограничиться тем, что операционная система сама знает, какой ToS назначить отправляемому IP-пакету.

Например, в пакетах telnet и ping ToS будет иметь разные значения.

0: — дескриптор корневой дисциплины.

Дескрипторы должны выглядеть так основной_номер: минорный_номер , но для дисциплин младшее число всегда должно быть 0, поэтому его можно опустить.

Параметр priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1 , просто указывает побитовое соответствие поля ToS каждой внутренней очереди (полосе).

Например, при ToS=4 пакет обрабатывается в очереди 1, при ToS=7 — в очереди 0. В ряде источников указано, что параметры дисциплины pfifo_fast изменить, поверьте, нельзя.



ТБФ
Теперь давайте посмотрим, как можно ограничить общую скорость исходящего трафика.

Для этого присвоим корневую дисциплину интерфейса дисциплине типа TBF (фильтр сегмента токенов) .

# tc qdisc add dev eth0 root скорость tbf 180 кбит, задержка 20 мс, буфер 1540 скорость 180 кбит — устанавливает порог скорости передачи на интерфейсе.

задержка 20 мс — устанавливает максимальное время, которое пакет данных проводит в ожидании токена.

буфер 1540 — установить размер буфера токена в байтах.

В примерах пишут, что для ограничения 10Мбит/с достаточно буфера в 10Кбайт. Главное не делать его слишком маленьким, можно и побольше.

Примерная формула расчета: скорость_в_байтах/100.

Для новичков об управлении шириной канала в Linux

Дисциплина TBF использует для своей работы механизм токенов.

Токены генерируются системой с постоянной скоростью и помещаются в буфер (корзину).

Для каждого токена, покидающего буфер, IP-пакет покидает интерфейс.

Если скорость передачи пакетов и генерации токена совпадают, процесс передачи данных происходит без задержек.

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

Если скорость передачи пакетов выше, то токенов будет не хватать.

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

Две описанные дисциплины относятся к так называемым бесклассовым дисциплинам.

У них есть ряд функциональных ограничений: они подключаются только к интерфейсу (или классу Edge), плюс к ним нельзя применить пакетные фильтры.

И соответственно мою задачу по балансировке почтового трафика с их помощью решить невозможно.

Кстати, полный набор бесклассовых дисциплин несколько шире: pfifo, bfifo, sqf (обеспечивает одинаковую скорость поступления пакетов из разных потоков), esqf и т.д.

Классные дисциплины

Если дисциплины можно представить как участки водопроводных труб, то классы – это соединители (фитинги).

Это может быть простой штуцер-переходник, а может быть хитрый штуцер-разветвитель с десятком изгибов.

Родителем класса может быть либо дисциплина, либо другой класс.

Дочерние классы можно присоединить к классу (объединив несколько фитингов).

Класс, не имеющий дочерних классов, называется край (класс листа) .

Здесь пакеты данных, пролетев через нашу «водопроводку», покидают систему управления трафиком и отправляются сетевым интерфейсом.

По умолчанию к любому пограничному классу прикреплена дисциплина типа fifo, и именно она определяет порядок передачи пакетов для этого класса.

Но прелесть в том, что мы можем заменить эту дисциплину на любую другую.

Если добавляется дочерний класс, данная дисциплина удаляется.



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

предварительно .

Он очень похож на уже описанный pfifo_fast. Но особенность этой дисциплины состоит в том, что при ее назначении автоматически создаются три класса (количество можно изменить с помощью параметраbands).

Давайте заменим корневую дисциплину интерфейса на prio. # tc qdisc добавить корневой дескриптор dev eth0 1: prio ручка 1: — установить дескриптор для этого корневого qdisc. В классных дисциплинах потом указывается при подключении занятий.

Проверка дисциплины: # tc qdisc qdisc prio 1: dev eth0bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1 Проверяем классы: # tc -d -s class show dev eth0 класс prio 1:1 родительский 1: Отправлено 734914 байт 7875 pkt (отброшено 0, превышено 0, запрошено 0) невыполненные запросы 0b 0p 0 класс prio 1:2 родительский 1: Отправлено 1555058583 байт 8280199 пкт (отброшено 124919, превышено 26443 запроса 0) невыполненных запросов 0b 0p запросов 0 класс prio 1:3 родительский 1: Отправлено 57934378 байт 802213 пкт (отброшено 70976, превышено 284608 запросов 0) невыполненные запросы 0b 0p 0 Мы видим три класса с идентификаторами 1:1, 1:2 и 1:3, подключенные к родительской дисциплине 1: type prio (классы должны иметь общий номер major_identifier со своим родителем).

То есть мы установили на корневой «пайп» qdisc тройник, который разделяет потоки данных так же, как это делает pfifo_fast. Согласно ToS, высокоприоритетный трафик переходит в класс 1:1, обычный трафик — в класс 1:2, а совсем «мусорный» — в класс 1:3. Допустим, обратный канал ADSL обеспечивает скорость 90 Кбит/с.

Давайте разделим это на 20Кбайт/с для почты и 70Кбайт/с для всего остального.

Мы не будем специально ограничивать трафик из класса 1:1. Его пакеты всегда смогут занять как минимум всю ширину канала благодаря высокому приоритету ToS, но объем трафика в этом классе будет незначительным по сравнению с двумя другими классами.

Поэтому мы не выделяем для него отдельную полосу.

Стандартный трафик обычно попадает в класс 1:2. Подключаем дисциплинарный канал 70Кбайт/с ко второму выводу тройника: # tc qdisc add dev eth0 родительский дескриптор 1:2 10: скорость tfb 70 кбит/с, буфер 1500, задержка 50 мс Подключим к третьему пину тройника дисциплинарный пайп 20Кбайт/с: # tc qdisc add dev eth0 родительский дескриптор 1:3 20: скорость tfb 20 кбит/с, буфер 1500, задержка 50 мс Все три этих класса являются маргинальными.

И теперь остаётся только направить почтовый трафик не в класс 1:2, как это было раньше, а в класс 1:3. Это делается с помощью фильтров дисциплины класса.

# фильтр tc добавить dev eth0 родительский 1: протокол ip prio 1 u32 match ip dport 25 0xffff flowid 1:3 родитель 1: — фильтр можно только прикрепить к дисциплине и вызвать из нее.

На основании ответа фильтра дисциплина решает, в каком классе пакет будет продолжать обрабатываться.

протокол IP — определить тип сетевого протокола прио 1 — параметр меня долго смущал, так как он используется в классах и фильтрах, плюс это название дисциплины.

Здесь prio задает приоритет фильтров, фильтры с меньшим prio активируются первыми.

и32 - так называемый классификатор трафика, который может отбирать пакеты по любым его характеристикам: по IP-адресу отправителя/получателя, по порту источника/получателя, по типу протокола.

Эти условия, собственно, и указаны ниже.

соответствие ip dport 25 0xffff — устанавливает фильтр, который будет срабатывать при отправке пакетов на порт 25. 0xffff — битовая маска номера порта.

текучий 1:3 — указать, в какой класс отправляются пакеты при срабатывании этого фильтра.

Это грубо сделано, но оно выполнит свою работу.

Посмотрим на статистику прохождения пакетов: # tc -s -d qdisq show dev eth0 # tc -s -d class show dev eth0 # tc -s -d filter show dev eth0 Быстро удалить все классы, фильтры и вернуть корневой интерфейс qdisc в исходное состояние можно командой: # tc qdisc del dev eth0 root

ХТБ
С другой стороны, наш обратный канал уже слишком тонкий, чтобы зарезервировать 20 КБ/с только для отправки электронной почты.

Поэтому здесь лучше использовать дисциплину класса HTB (Hierarchical Token Bucket).

Это позволяет дочерним классам заимствовать пропускную способность у родителя.



Для новичков об управлении шириной канала в Linux

# tc qdics добавить корневой дескриптор dev eth0 1: htb по умолчанию 20 по умолчанию 20 — установить класс по умолчанию.

Он будет обрабатывать пакеты, не вошедшие в другие классы дисциплины htb. Если вы не укажете его, будет присвоено значение «по умолчанию 0», и весь неклассифицированный (нефильтрованный) трафик будет отправляться со скоростью интерфейса.

# tc class add dev eth0 родительский 1: classid 1:1 htb скорость 90 кбит/с ячейка 90 кбит/с прикрепите класс с идентификатором 1:1 к корневому qdisc. Таким образом мы ограничиваем скорость на интерфейсе до 90 КБ/с.

класс 1:1 — идентификатор класса.

скорость 90 кбит/с — установить нижний порог пропускной способности для класса.

ячейка 90 кбит/с — устанавливаем верхний порог пропускной способности для класса.

# tc class add dev eth0 родительский 1:1 classid 1:10 htb скорость 20кбит/с ячейка 70кбит/с создайте класс 1:10, дочерний класс 1:1. Тогда фильтр будет направлять на него исходящий почтовый трафик.

скорость 20 кбит/с — мы устанавливаем гарантированно нижний порог пропускной способности для класса.

ячейка 70 кбит/с — устанавливаем верхний порог пропускной способности для класса.

Если у родительского класса есть свободная пропускная способность (наличие «лишних» токенов), класс 1:10 сможет временно увеличить скорость передачи данных, до указанного лимита в 70 Кб/с.

# tc class add dev eth0 родительский 1:1 classid 1:20 htb скорость 70 кбит/с ячейка 90 кбит/с Создайте класс по умолчанию.

Весь остальной трафик попадет в него.

Таким же образом с помощью параметровrate и ceil задаем расширение пропускной способности в случае отсутствия почтового трафика.

# фильтр tc добавить dev eth0 родительский 1: протокол ip prio 1 u32 match ip dport 25 0xffff flowid 1:10 фильтр на основе u32, который направляет исходящие пакеты на порт 25 в класс 1:10. Кстати, в документации указано, что на самом деле в HTB формирование трафика происходит только в классах Edge, в нашем случае 1:10 и 1:20. Указание параметров ограничения пропускной способности в остальных классах HTB необходимо только для функционирования системы заимствований между классами.

При добавлении класса также можно указать параметр предварительно .

Он определяет приоритет класса (0 — максимальный приоритет).

Классы с более низким приоритетом не обрабатываются, пока есть данные в классах с более высоким приоритетом.

Источники: HOWTO по расширенной маршрутизации и управлению трафиком в Linux HOWTO по управлению трафиком Повесть о Linux и управлении трафиком Теги: #linux #настройка Linux #трафик #трафик #tc #iproute2 #пропускная способность

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.