Шейпер — это программа, осуществляющая ограничение скорости. Шейпер работает по алгоритму, который управляет очередностью пакетов данных и ограничивает скорость путем отбрасывания пакетов, не удовлетворяющих определенным условиям.
HTB Шейпер
В различных операционных системах шейперы реализованы по разному.
В Windows шейперы представляют собой программные пакеты, в основном платные и практически не настраиваемые.
В Linux гораздо больше простора для создания шейперов, поскольку операции с сетевыми пакетами встроены непосредственно в ядро операционной системы. За счет этого достигается лучшее быстродействие и надежность.
В Linux шейпер создается путем добавления требуемой очереди непосредственно к сетевому интерфейсу. Этот элемент называется qdisc (Queueing Discipline — Дисциплина организации очереди).
Дисциплина организации очереди (qdisc) — это алгоритм, который захватывает пакеты и определяет, в каком порядке и каким образом они будут двигаться. Задавая разные qdisc на интерфейсе, можно применять разные алгоритмы управления трафиком.
Дисциплины организации очереди делятся на два вида:
Безклассовые дисциплины организации очередей (Classless qdisc).
К ним относятся PRIO, Class Based Queueing (CBQ), Hierarchical Token Bucket (HTB) и т.д. В дальнейшем такие qdisc будем называть просто «дисциплина». Они являются костяком для организации иерархии из очередей.
Управление пропускной способностью в Mikrotik RouterOS основано на дисциплине HTB (Hierarchical Token Bucket). Она одна из самых удобных, простых и надежных дисциплин для организации шейпера.
В Mikrotik RouterOS есть следующие основные возможности по управлению трафиком:
HTB позволяет организовать древовидную иерархию из очередей и направлять в них трафик при помощи системы фильтров. Для понимания принципа работы HTB рассмотрим следующую аналогию:
Есть дорога, по которой ходят трамвай, троллейбус и такси. Согласно ПДД скорости каждого из транспортных средств строго определены — у трамвая это 40 км/ч, у троллейбуса — 70 км/ч и у такси — 100 км/ч. У каждого из транспортов на дороге своя полоса. У трамвая — рельсы, у троллейбуса — дорога под проводами. Ну а у такси вся остальная дорога. Пассажиры выбирают транспорт в соответствии со своим достатком или желанием. Те, кто побогаче — едут на такси, самые бедные — на трамвае, ну а средний класс — на троллейбусе.
HTB состоит из следующих элементов:
Таким образом, трафик сначала отфильтровывается в соответствующую очередь, а затем движется по ней (точнее выдается из нее) со скоростью, определённой в классе. На практике это работает именно в таком порядке. Хотя первым делом пакет проходит фильтр.
Из классов строится иерархия HTB. Иерархия нужна для сложного распределения скорости пакетов в классах. Нижестоящие классы получают разрешенную скорость от вышестоящих.
Пример иерархии классов HTB можно увидеть на рисунке ниже. Иерархия представлена в виде некого гибридного дерева разделенного уровнями Level0, Level1, конечными вершинами которого являются клиенты или листья Leaf1, Leaf2. Классы, которые не имеют дочерних, будем называть клиентами или листьями. Обычно они находятся на нулевом уровне иерархии и первыми захватывают относящийся к ним трафик, передавая его родителям. Два или более класса, имеющие одного прямого родителя находятся на одном уровне и подсоединены к одной локальной выходной очереди.
Схематическое изображение структуры HTB.
В иерархию классов из файервола (Filter) поступают пакеты с данными. В зависимости от приоритета, параметров классов и загрузки канала они попадают или в локальные очереди (Self Feed), или передаются в очереди родительских классов (Inner Feed).
Любой класс HTB обладает следующими параметрами:
Класс может находиться в одном из трех состояний:
Рассмотрим несколько примеров работы HTB.
Выполните в консоли New Terminal следующие команды:
1. Рассмотрим первый случай, когда листья Leaf1 и Leaf2 передают данные со скоростью меньше, чем указано в параметре limit-at, а Leaf3 не работает.
Как видим, пакеты с данными от leaf1 и leaf2 (клиенты) не передаются в родительские классы, а выстраиваются в локальную очередь в соответствии со своими приоритетами.
2. Теперь посмотрим что будет, в случае если клиент leaf2 будет передавать данные со скоростью больше limit-at, но меньше max-limit указанных в его параметрах и меньше limit-at в параметрах ClassB, к которому он прикреплен. Одновременно с ним leaf1 будет передавать данные со скоростью не превышающей limit-at.
В данном случае получается интересная ситуация: клиент leaf1 будет иметь больший приоритет, чем leaf2, хотя в параметрах последнего указан больший приоритет. Это связано с тем, что передавая данные со скоростью более limit-at leaf2 подключился к родительскому классу, имеющему приоритет 8. При этом существует правило, что на нижних уровнях приоритет пакетов при одинаковых условиях больше, чем на верхних.
3. Рассмотрим следующий пример: скорости передачи данных для leaf1 превысила допустимое max-limit, клиент leaf2 передает данные на скорости больше limit-at и меньше max-limit, клиент leaf3 работает на скорости меньше limit-at.
Это весьма интересный случай. В данной ситуации видно, что ClassA перегружен данными из Leaf1, поэтому ClassB не получит разрешения на передачу. В результате работоспособным окажется только клиент leaf3, подключенный в локальную очередь на нулевом уровне.
4. Теперь рассмотрим пример, когда данные будут одновременно передавать leaf1, leaf2, leaf3, ClassB будет желтым, а ClassA зеленым.
В результате этого на втором уровне leaf2 попадет в очередь первым (так как имеет больший приоритет), а leaf1 и leaf3 подвергнутся случайному выбору для определения порядка следования.
Алгоритм работы HTB весьма логичен. Он был принят многими производителями программного и аппаратного обеспечения за свою гибкость, надежность и отсутствие свойственных его предшественникам недостатков. Благодаря огромной универсальности с помощью него можно строить практически любые возможные иерархии правил, в точности разграничивая и давая возможность управлять потоками данных на достаточно низком уровне.
Пиковая скорость Burst
Пиковая скорость Burst применяется для того, чтобы выдать клиенту максимальную скорость на определенный промежуток времени.
Например, вам нужно ускорить загрузку страниц, и при этом ограничить скорость на закачку файлов. Или нужно изредка передавать и принимать данные, но делать это с максимальной скоростью.
Если клиенту изначально дать большую скорость, то он может поставить файлы на закачку и оставить остальных пользователей без интернета. В этом случае нам помогут инструменты управления пиковой скоростью Burst.
Пиковая скорость обладает следующими параметрами:
Момент, когда клиенту или классу нужно выдать максимальную скорость, определяется следующим образом. Раз в 1/16 времени burst-time вычисляется загрузка канала на указанное число секунд. Если средняя загрузка составила менее burst-threshold, то клиенту или классу выделяется указанная в burst-limit скорость до тех пор, пока она не превысит burst-threshold. После этого действует ограничение max-limit до тех пор, пока снова не случится понижение скорости менее burst-threshold.
Установим следующие параметры limit-at=128000/128000, max-limit=256000/256000, burst-limit=512000/512000, burst-treshold=192000/192000, burst-time=8 и понаблюдаем, что случится с графиком загрузки канала от одного клиента:
Данный график характерен для случая с закачкой большого файла по протоколу http. После первой секунды средняя загрузка канала будет равна (0+0+0+0+0+0+0+512)/8=64 kbps, что менее установленного нами параметра burst-threshold. После второй секунды средняя скорость будет равна (0+0+0+0+0+0+512+512)/8=128kbps. После третьей секунды средняя скорость превысит показатель burst-threshold. В этот момент скорость резко упадет до значения параметра max-limit и будет держаться на этом уровне до тех пор, пока средняя загрузка канала не станет меньше burst-threshold и снова не произойдет выдача burst скорости.
Алгоритмы Schedulers
Алгоритмы Schedulers предназначены для формирования очередей данных по каким-то параметрам и последующей передаче их шейперу. Например, можно сформировать очереди данных по приоритетам пакетов, адресу источника или получателя. Некоторые алгоритмы обладают функциями ограничения скорости.
PFIFO/BFIFO
Packet/Bytes (FIFO) алгоритм основан на принципе первый пришел-первый ушел. Тот, кто пришел первым, тот и обслуживается первым. Пришедший следующим ждёт, пока обслуживание первого не будет закончено, и так далее.
Для настройки алгоритма используется единственный параметр pfifo-limit (bfifo-limit). Он указывает на количество байт, которые могут храниться в выходном буфере. Не попавшие в буфер пакеты будут разрушаться. Алгоритм применяется для ethernet интерфейсов.
SFQ
SFQ (Stochastic Fairness Queuing) – этот алгоритм можно назвать "случайно-честным". Он применяется тогда, когда требуется предоставить всем TCP/UDP-подключениям одинаковую возможность по передаче данных.
Для конфигурирования SFQ используется два параметра:
SFQ работает по следующему принципу: алгоритм изымания пакетов из под-очередей одновременно выпускает в выходной интерфейс pcq-allot количество байт, а хэширующий алгоритм добавляет к каждый под-очереди pcq-allot байт, сохраняя при этом равновесие и одинаковую длину всех подочередей. Схему работы SFQ можно сравнить с мясорубкой, в которой через выходную решетку одновременно изо всех дырок в одинаковом количестве выходит фарш.
Алгоритм SFQ рекомендуется использовать в случаях, когда канал сильно загружен и необходимо предоставить приложениям одинаковую возможность по передаче данных. Единственным его недостатком является то, что одно приложение (например торрент клиент), открыв много потоков, может заглушить остальные подключения.
PCQ
PCQ (Per Connection Queuing) является частным случаем SFQ за тем исключением, что формирование потоков в под-очереди будет происходить в соответствии с неким правилом. Это может быть адрес источника/получателя и порт источника/получателя. Таким образом можно равномерно распределить скорость между участниками вне зависимости от количества открытых подключений. Алгоритм предоставляет следующие параметры для конфигурирования:
Данный алгоритм является основным при необходимости разделить пропускную способность поровну между классами или клиентами. С его помощью можно организовать динамический шейпинг.
Классифицировав под-очереди по адресу источника мы получим отдельную очередь для каждого адреса, соответственно количество потоков с одного адреса не будет играть роли при доступе к выходному интерфейсу. Стоит отметить гибкость такой классификации. Применив ее по источнику к внешнему интерфейсу, в под-очереди будут попадать внешние адреса, так как в этом случае параметр src-address будет все равно содержать адрес, являющийся источником передачи данных. Применив эту же классификацию к внутреннему интерфейсу, в очереди попадут адреса клиентов или классов.
Таким образом, задав два правила, отличающиеся одним параметром, можно разделить поровну как входящий, так и исходящий каналы.
RED
RED (Random Early Detection) — алгоритм, призванный выравнивать пропускную способность и сглаживать скачки, контролируя средний размер очереди. Когда ее размер достигает значения red-min-threshold алгоритм удаляет случайно выбранный пакет. Число удаленных пакетов растет с увеличением среднегого размера очереди. Если размер достигает значения red-max-threshold все пакеты удаляются. Однако случаются ситуации, когда реальный размер очереди (не средний) значительно больше red-max-threshold. В таком случае все пакеты, выходящие за рамки предела red-limit, удаляются.
Использование алгоритма крайне не желательно при присутствии UDP трафика, так как в связи с неразборчивостью алгоритма при удалении пакетов из очереди и принципом работы UDP-протокола, данные могут не дойти до получателя.
На практике алгоритмы SFQ и RED используется крайне редко.
Типы очередей
В Mikrotik предусмотрены два типа очередей, разнесенные на разные закладки в графической утилите Winbox:
Queue Trees
Queue Trees - особый тип очередей, который прямо отражает устройство шейпера HTB. Он позволяет строить деревья правил (классов) и на самом низком уровне управлять пакетами.
Основные параметры Queue Trees:
Создадим правило, которое позволит получить клиентам локальной или виртуальной сети максимальную скорость и минимальное время отклика при обращении к сайту www.drivermania.ru , однако разделит скорость между всеми поровну.
1. Пометим все пакеты, идущие от пользователей на адрес 66.148.73.54 и обратно. Для этого нужно создать 4 правила, два из которых пометят подключения в прямом и обратом направлении, а другие два пометят пакеты в этих подключениях. Необходимо обратить внимание, что очереди работают именно с пакетами, а не помеченными подключениями. Зачастую это создает у новичков вопросы плана: "Я пишу все правильно, а оно не работает. Может это глюки?" Для таких шаманов ниже приведен пример, как нужно делать, чтобы оно работало.
2. Создадим два типа PCQ очереди, подключения в одной из которых мы будем классифицировать по входящему, а другие по исходящему адресу.
3. Создадим очереди для входящего и исходящего трафика
Практически в Queue Trees мы можем оперировать только ограничением скорости. Остальные параметры, такие как адрес источника, получателя, время суток, протокол, порты и т.д. указываются в разделе Mangle-файервола.
Подобным способом также можно сделать хороший пинг на определенные адреса, даже во время серьезной загрузки канала. Приведем пример таких правил для сервера www.cybernet.by.
Для этого нужно создать четыре правила в Firewall:
Следующим шагом создадим два правила в Queue Trees: одно для входящего потока, другое - для исходящего.
Вышеописанные действия позволят пакетам, приходящим и уходящим с адреса 195.222.70.250, попадать в приоритетные очереди и всегда иметь гарантированные 50 Kbit/s.
Пользуясь вышеописанным примером можно выделить для всех онлайн игр фиксированную гарантированную скорость и создать иерархию классов (правил), распределив, таким образом, пропускную способность между всеми поровну.