8. Аппаратная реализация QoS
Last updated
Last updated
В этой главе я беру на себя неблагодарную задачу. Если описывать максимально просто, всегда найдутся те, кто скажет, что всё не так на самом деле.
Если описывать как есть, читатель бросит статью, потому что она превратится в чертёж подводной лодки, точнее чертежи трёх лодок карандашами разного цвета на одном листе. В общем, сделаю дисклеймер, что в действительности всё не так, как на самом деле, и пойду по варианту простого изложения. Да простит меня мой попутчик-перфекционист.
Что управляет поведением узла и запускает соответствующие механизмы по отношению к пакету? Приоритет, который он несёт в одном из заголовков? И да, и нет.
Как уже говорилось выше, внутри сетевого устройства обычно перестаёт существовать стандартный коммутирующий заголовок.
Как только пакет попал на чип коммутации, заголовки с него снимаются и отправляются на анализ, а полезная нагрузка томится в каком-то временном буфере.
На основе заголовков происходит классификация (BA или MF) и принимается решение о пересылке. Через мгновение на пакет навешивается внутренний заголовок с метаданными о пакете. Эти метаданные несут много важной информации — адреса отправителя и получателя, выходной чип, порядковый номер ячейки, если была фрагментация пакета и обязательно маркировку класса (CoS) и приоритет отбрасывания (Drop Precedence). Только маркировку во внутреннем формате — он может совпадать с DSCP, а может и нет. В принципе, внутри коробки можно задать произвольную длину маркировки, не привязываясь к стандартам, и определять очень гибко действия с пакетом. У Cisco внутренняя маркировка зовётся QoS Group, у Juniper — Forwarding Class, Huawei не определился: где-то называет internal priorities, где-то local priorities, где-то Service-Class, а где-то просто CoS. Добавляйте в комментарии названия для других вендоров — я дополню.
Вот эта внутренняя маркировка назначается на основе классификации, которую выполнил узел.
Важно, что если не сказано иного, то внутренняя маркировка работает только внутри узла, но никак потом не отображается на маркировку в заголовках пакета, который будет отправлен с узла — она останется прежней. Однако, на входе в DS-домен после классификации обычно происходит перемаркировка в определённый класс сервиса, принятый в данной сети. Тогда внутренняя маркировка преобразуется в значение, принятое для данного класса на сети, и записывается в заголовок отправляемого пакета. Внутренняя маркировка CoS и Drop Precedence определяет поведение только внутри данного узла и никак явным образом не передаётся соседям, кроме перемаркировки заголовков. CoS и Drop Precedence определяют PHB, его механизмы и параметры: предотвращение перегрузок, управление перегрузками, диспетчеризация, перемаркировка.
Через какие круги проходят пакеты между входным и выходным интерфейсами я рассмотрел в предыдущей статье. Собственно она и оказалась внеплановой, поскольку в какой-то момент стало очевидно, что без понимания архитектуры говорить о QoS преждевременно.
Однако, давайте повторимся.
Сигнал попадает на физический входной интерфейс и его чип (PIC). Из него восстанавливается битовый поток и потом пакет со всеми заголовками.
Далее на входной чип коммутации (FE), где заголовки отделяются от тела пакета. Происходит классификация и определяется, куда пакет нужно отправить дальше.
Далее во входную очередь (TM/VOQ). Уже здесь пакеты раскладываются в разные очереди на основе своего класса.
Далее на фабрику коммутации (если она есть).
Далее в выходную очередь (TM).
Далее в выходной чип коммутации (FE), где навешиваются новые заголовки.
Далее в выходной интерфейс (возможно, через ещё одну очередь) (PIC).
При этом маршрутизатор должен решить сложное уравнение. Разложить всё по классам, предоставить кому-то широкую полосу, кому-то низкие задержки, кому-то обеспечить отсутствие потерь. И при этом успеть пропустить по возможности весь трафик. Кроме того, нужно сделать шейпинг, возможно, полисинг. Если вдруг имеет место перегрузка, то справиться с ней. И это не считая лукапов, обработки ACL, подсчёта статистик. Незавидная доля. Но вкалывают роботы, а не человек.
На самом деле есть всего два места, где работают механизмы QoS — это чип коммутации и чип Traffic Management/очереди. При этом на чипе коммутации происходят операции, которые требуют анализа или действий с заголовками.
Классификация
Полисинг
Перемаркировка
Остальное берёт на себя TM. В основном это рутинные операции с предопределённым алгоритмом и настраиваемыми параметрами:
Предотвращение перегрузок
Управление перегрузками
Шейпинг
TM — это умный буфер, обычно на основе SD-RAM. Умный он потому что, а) программируемый, б) с очередями умеет делать всякие хитрые штуки. Зачастую он распределённый — чипы SD-RAM расположены на каждой интерфейсной плате, и все вместе они объединяются в VOQ (Virtual Output Queue), решающий проблему Head of Line Blocking. Дело в том, что если чип коммутации или выходной интерфейс захлёбывается, то они просят входной чип притормозить и не отправлять некоторое время трафик. Если там только одна очередь на все направления, то очень обидно, что из-за одного выходного интерфейса страдают все остальные. Это и есть Head of Line Blocking. VOQ же создаёт на входной интерфейсной плате несколько виртуальных выходных очередей для каждого существующего выходного интерфейса. Причём эти очереди в современном оборудовании учитывают и маркировку пакета. Про VOQ достаточно подробно описано в серии заметок здесь.
К слову реально в очереди помещаются, по ним продвигаются, из них изымаются итд не сами пакеты, а только записи о них. Нет смысла делать такое количество телодвижений с большими массивами битов. Пока над записями измывается QoS, пакеты прекрасно себе лежат в памяти и извлекаются оттуда по адресу.
VOQ - это программная очередь (английский термин Software Queue более точен). После него сразу перед интерфейсом находится ещё аппаратная очередь, которая всегда, строго работает по FIFO. Управлять какими-либо её параметры практически невозможно (для примера, Cisco позволяет настроить только глубину командой tx-ring-limit).
Как раз между программной и аппаратной очередью можно запускать произвольные диспетчеры. Именно в программной очереди работают Head/Tail-drop и AQM, полисинг и шейпинг.
Размер аппаратной очереди очень небольшой (единицы пакетов), потому что всю работу по укладыванию в line-rate делает диспетчер.
К сожалению, здесь можно сделать много оговорок, да и вообще всё перечеркнуть красной ручкой и сказать «у вендора Х всё не так».
Хочется сделать ещё одно замечание о служебных пакетах. Они обрабатываются иначе, чем транзитные пользовательские пакеты.
Будучи сгенерированными локально, они не проверяются на подпадание под правила ACL, и ограничения скорости.
Пакеты же извне, предназначенные на CPU, с выходного чипа коммутации попадают в другие очереди — к CPU — на основе типа протокола.
Например, BFD имеет наивысший приоритет, OSPF может подождать подольше, а ICMP и вообще не страшно отбросить. То есть, чем важнее пакет для работоспособности сети, тем выше его класс сервиса при посылке на CPU. Именно поэтому видеть в пинге или трассировке варьирующиеся задержки на транзитных хопах — это нормально — ICMP — не приоритетный для CPU трафик. Кроме того, на протокольные пакеты применяется CoPP — Control Plane Protection (или Policing) — ограничение скорости во избежание высокой загрузки CPU — опять же, лучше предсказуемые отбрасывания в низкоприоритетных очередях до того, как начались проблемы. CoPP поможет и от целенаправленного DoS и от аномального поведения сети (например, петли), когда на устройство начинает приходить много широковещательного трафика.