четверг, 21 июля 2016 г.

Базовый QoS и Можжевельник

В моей сетевой жизни было три темы, которые в той или иной мере с трудом заходили мне в голову. Multicast, MPLS, QoS. С первыми двумя я нашел силы и разобрался. Не сказать, что я чувствую прям сильные знания, но что-то могу собрать в своей голове. С QoS все не просто. Иногда кажется, что это почти религия. Я прочитал довольно много материалов по QoS, но по какой-то причине мало что остается в голове с течением времени. Недавно напоролся на брошюрку от Juniper из серии Day One, которая довольно складно и без лишней информации рассказывает про базовый Quality of Service. Вообще, очень рекомендую бесплатные материалы от Junos из серии Day One, да и вообще информацию на их сайте. Must have, как говориться. Часто меня выручал сайт Juniper, когда я решал проблемы с Cisco, D-Link или ещё чем-нибудь. Есть у них совсем прикольные штуки типа Junos QoS for IOS Engineers.

Ладно, коротко о QoS...
Quality of Service (QoS) - это методика манипулирования потоками трафика для того чтобы они начали соответствовать заданным условиям. Простой пример, когда вы качаете сериальчик через торрент на максимальной скорости и одновременно пытаетесь позвонить через тот же скайп, может возникнуть легкий конфуз. Случается это потому, что сетевое оборудование не знает о приоритетах и рассматривает весь трафик как одинаковый. А вот если бы ему можно было объяснить, какому трафику отдать приоритет, то и торенты бы качались (пусть не на максимальной скорости) и по скайпу можно было бы позвонить. Пример, на мой вкус, не самый удачный, но общее понимание дает.

У любого трафика есть как минимум три характеристики, которые важный для QoS:
  • Потери - потери кадров, которые происходят между двумя точками
  • Задержки - задержка между временем отправки трафика и временем его доставки получателю
  • Джиттер - это вариативность задержки. 
Большие значения этих характеристик могут стать проблемой для того или иного сервиса. Для примеров удобно брать Voice-over-IP (VoIP). Возьмем два телефона и некую сеть между ними. Первый телефон принимает аналоговый сигнал, цифрует его и разбивает на пакеты, которые отправляет в сеть. Сеть эти пакеты передает, а второй телефон выполняет обратную процедуру. Собирает достаточное количество пакетов для того чтобы сделать их них аналоговый сигнал и отправляет его пользователю в ухо. При потерях на сети, часть пакетов не дойдет до пользователя, поэтому связь будет прерываться. При большой задержке, разговор не будет клеиться. Либо абоненты будут начинать одновременно говорить, либо паузы будут мхатовскими. Джиттер тоже будет доставлять потерь. В тот момент, когда телефон должен будет взять пачку кадров и преобразовать их в аналоговый сигнал, части кадров может и не быть. Потому как они ещё не успели дойти.

QoS - это комплекс мероприятий, который должен производится на всех устройствах, через которые проходит интересующий нас трафик.

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

-> CLASSIFICATION -> POLICING -> QUEUING -> SHAPING -> REMARKING ->

Classification

Это определение какому классу соответствует тот или иной трафик. Каждый вендор придумывает свои подходы, рассмотрим Juniper'овский.
  1. Interface Based - все что пришло в интерфейс соотносится к тому или иному классу.
  2. Behaviour Aggregate - классификация на основе уже имеющихся в трафике указателей. Такой подход часто используется внутри сети, когда пограничные устройства уже классифицировали трафик.
    • Ethernet - 802.1p
    • IPv4 - Type of Service
    • MPLS - Experimental bits
  3. Multifield - классификация производится на основе правил файервола и полагается на всю функциональность access-list (ACL)

Policing

По сути, это простое лимитирование трафика, причем довольно жесткое и выполняющиеся ещё до самых важных QoS процессов. В Juniper есть три вида полисинга:
  • Single-Rate Two-Color 
Есть оговоренная полоса пропускания. Если трафик не выходит за неё, то он находится в Зеленой зоне. Если выходит, то трафик попадает в Красную зону и может быть либо сразу отброшен, либо переклассиицирован. Так же, есть такое понятие как burst. Это некое расширение зеленой зоны, попадая в эту зону трафик ещё не будет отброшен.
  • Single-Rate Three-Color 
Вводится три понятия. Первое из них - commited information rate (CIR), которое определяет зеленую зону. Трафик между commined burst size (CBS) и excees burst size (EBS) находится в желтой зоны. Выше EBS трафик попадает в красную зону. На каждую из зон можно определить значение количества отбрасываемых пакетов. 
  • Two-Rate Three-Color 
Трафик внутри CIR находится в зеленой зоне.Трафик между CIR и peak information rate (PIR) находится в желтой зоне, выше PIR находится красная зона. Можно ещё и burst'ов навесить.

Queuing/Shaping

Тут-то все и происходит. В Juniper эти два понятия неразрывно связаны. 
Queuing - процесс распределения трафика в очереди, так же называется scheduling.  Очереди имеют несколько характеристик:
  • Transmission rate
  • Priority
  • Delay buffer
  • Drop profiles
Shaping -  контролирование исходящей пропускной способности очередей.

В Juniper весь процесс Queuing/Shaping настраивается через следующие сущности:
Forwarding Classes - просто декларация классов и соответствие их очередям.
Schedulers - это некий набор характеристик (обозначены выше), которые могут быть применены на ту или иную очередь.
Schedulers-map - нечто соединяющее scheduler и forwarding class.

Думаю, на примере все будет понятней.

Настройка


Рассмотрим простой пример настройки QoS на Juniper, который представлен в их же документации. Случай довольно простой, но он дает понимание о взаимоотношениях между основными структурными блоками. Придется перейти на моноширинный текст, прошу прощения.

1. Определяется 8 классов. 
  • Один класс NC (Network Control) c высоким приоритетом и с седьмой очередью
  • Один класс EF (Expedited Forwarding) c высоким приоритетом и пятой очередью
  • Четыре класса AF(Assured Forwarding) с приоритетом выше среднего и ниже среднего и с очередями 4,3,2,1
  • Один класс BE (Best-Effort) c низким приоритетом и нулевой очередью
  • Один класс (Less than Best-Effort) с низким приоритетом и шестой очередью
class-of-service {
forwarding-classes {
class NC queue 7 priority high;
class EF queue 5 priority high;
class AF11 queue 4 priority medium-high;
class AF13 queue 3 priority medium-high;
class AF22 queue 2 priority medium-low;
class AF42 queue 1 priority medium-low;
class BE queue 0 priority low;
class LBE queue 6 priority low;
}


2. Определяются "классификаторы". Тут указан пример для Behaviour Aggregate классификации, которая основывается на значениях EXP битов в MPLS заголовке. Другими словами, мы доверяем предыдущему устройству, которое уже классифицировало трафик. Определяется соответствие:
  • класса (был обозначен в прошлом пункте), 
  • loss-priority (вероятность того, что пакет будет отброшен в случае перегруженности канала)
  • code-point (последовательность бит в заголовке MPLS)
classifiers {
exp BA_CORE_EXP_CLASSIFIER {
forwarding-class NC {
loss-priority low code-points 111;
}
forwarding-class EF {
loss-priority low code-points 101;
}
forwarding-class AF11 {
loss-priority low code-points 100;
}
forwarding-class AF13 {
loss-piority high code-points 011;
}
forwarding-class AF22 {
loss-priority medium code-points 010;
}
forwarding-class AF42 {
loss-priority medium code-points 110;
}
forwarding-class BE {
loss-priority high code-points 000;
}
forwarding-class LBE {
loss-priority high code-points 001;
}
}
}


3. Определяются "шедуллеры".  Всего их семь, у каждого из них есть:
  • определенный transmit-rate (в некоторых случаях с rate-limit, т.е. трафик имеет гарантированный процент полосы, но не более того)
  • размер буфера в процентах  (percent), в микросекундах (temporal) или по остаточному принципу (reminder)
  • приоритет
  • дополнительно можно навесить drop-profile, которые определяются ниже по конфигу
schedulers {
HIGH_5PC_5PC_SCHEDULER {
transmit-rate percent 5;
buffer-size percent 5;
priority high;
}
HIGH_50PC_RL_20MS_SCHEDULER {
transmit-rate percent 50 rate-limit;
buffer-size temporal 20000;
priority high;
}
MEDIUM_HIGH_10PC_20PC_SCHEDULER {
transmit-rate percent 10;
buffer-size percent 20;
priority medium-high;
}
MEDIUM_HIGH_10PC_10PC_SCHEDULER {
transmit-rate percent 10;
buffer-size percent 10;
priority medium-high;
drop-profile-map loss-priority high protocol any drop-profile AGGRESSIVE;
}
MEDIUM_LOW_10PC_10PC_SCHEDULER {
transmit-rate percent 10;
buffer-size percent 10;
priority medium-low;
drop-profile-map loss-priority high protocol any drop-profile MODERATE;
}
LOW_5PC_20PC_SCHEDULER {
transmit-rate percent 10;
buffer-size percent 20;
priority low;
drop-profile-map loss-priority high protocol any drop-profile AGGRESSIVE;
}
LOW_REM_REM_SCHEDULER {
transmit-rate remainder;
buffer-size remainder;
priority low;
drop-profile-map loss-priority any protocol any drop-profile AGGRESSIVE;
}
}


4. Связываем "шедуллеры" и классы c помощью scheduler-map. В конфиге ниже каждому созданному ранее классу соответствует определенный шедуллер.

scheduler-maps {
CORE_UPLINK_SCHED_MAP {
class NC scheduler HIGH_5PC_5PC_SCHEDULER;
class EF scheduler HIGH_50PC_RL_20MS_SCHEDULER;
class AF11 scheduler MEDIUM_HIGH_10PC_20PC_SCHEDULER;
class AF13 scheduler MEDIUM_HIGH_10PC_10PC_SCHEDULER;
class AF22 scheduler MEDIUM_LOW_10PC_10PC_SCHEDULER;
class AF42 scheduler MEDIUM_LOW_10PC_10PC_SCHEDULER;
class BE scheduler LOW_10PC_10PC_SCHEDULER;
class LBE scheduler LOW_REM_REM_SCHEDULER;
}
}
5. Настраиваем drop-profile. Штука довольно прикольная. Сам принцип в регулировании количества отправляемого трафика от клиента. Т.е. наше устройство управляет количеством трафика, который отправляет клиент! Делается это для TCP, как правило, и представляет из себя рандомное отбрасывание пакетов для того чтобы отправляющее устройство начало уменьшать размер TCP окна. На этом этапе определяется ветвь параболы (уровень отбрасываемых кадров к уровню заполнения канала). В нашем примере ниже, для первого "агресивного" профиля определено следующее поведение:
  • когда канал заполнится на 25% шанс отбрасывания пакетов станет равен 40. 
  • при заполнении в 60%, шанс увеличивается до 80
  • ну и 80% соответствует 90.

drop-profiles {
AGGRESSIVE {
interpolate {
fill-level [25 60 80];
drop-probability [40 80 90];
}
}
MODERATE {
interpolate {
fill-level [50 75 95];
drop-probability [10 25 40];
}
}
}


6. Правила переписывания меток. В этом примере, биты в заголовке MPLS остаются без изменений, но, вообще, их можно было перебить на любые другие.



rewrite-rules {
exp CORE_EXP_REWRITE {
forwarding-class NC {
loss-priority low code-point 111;
}
forwarding-class EF {
loss-priority low code-point 101;
}
forwarding-class AF11 {
loss-priority low code-point 100;
}
forwarding-class AF13 {
loss-priority high code-point 011;
}
forwarding-class AF22 {
loss-priority medium code-point 010;
}
forwarding-class AF42 {
loss-priority medium code-point 110;
}
forwarding-class BE {
loss-priority high code-point 000;
}
forwarding-class LBE {
loss-priority high code-point 001;
}
}
}


7. Вешаем все это на интерфейс xe-0/0/0. Ниже видно, как на интерфейс навешен scheduler-map и rewrite-rules, что является последним аккордом в настройке QoS.



interfaces xe-0/0/0 {
unit 0 {
scheduler-map CORE_UPLINK_SCHED_MAP;
classifiers {
exp BA_CORE_EXP_CLASSIFIER;
}
rewrite-rules {
exp CORE_EXP_REWRITE;
}
}
}
}

8. Вишенкой на торте будет настройка полисера. Помним, что он применяется до основных операций QoS. Ниже создан Two-Rate Three-Color полисер, который устанавливает CIR в 2Mbps, burst в 5Kbps, PIR в 2500Kbps c burst в 5Kbps. Трафик, который выйдет за пределы PIK+burst будет отбрасываться с большой долей вероятности. 

firewall {
three-color-policer 2M_VOICE_SERVICE_POLICER {
two-rate {
color-aware;
committed-information-rate 2m;
committed-burst-size 5k;
peak-information-rate 2500k;
peak-burst-size 5k;
}
action {
loss-priority high then discard;
}
}

9. Настраиваем первый фильтр. Он будет определять трафик , который будет обрабатываться по принципам Best-Effort (как получится). Это такой дефолтный фильтр.

family inet {
filter UNTRUSTED_SUBSCRIBER_BLEACH_CLASSIFIER {
term BLEACH_DSCP {
then {
forwarding-class BE;
next term;
}
}
}

10. Настраиваем второй фильтр. Он чуть сложней и состоит из нескольких частей (term). Первая часть выделяет голосовой трафик по каким-то критериям (порт, IP...), а затем применяет к нему созданный в пункте 8 полисер и определяет его в Expedited Forwarding класс. Вторая часть выделяет второй тип трафика, который менее приортитетен и обрабатывает его как получится (Best-Effort). Остальной трафик так же обрабатывается как придется.


filter UNTRUSTED_SUBSCRIBER_MF_CLASSIFIER {
term VOICE_TRAFFIC_IN {
from {
$match_criteria_for_voice_service$;
}
then {
forwarding-class EF;
three-color-policer 2M_VOICE_SERVICE_POLICER;
accept;
}
}
term RECLASSIFY_OUT_OF_CONTRACT_VOICE {
from {
$match_criteria_for_voice_service$;
loss-priority high;
}
then {
forwarding-class BE;
}
}
term EVERYTHING_ELSE_IN {
then {
forwarding-class BE;
accept;
}
}
}
}
}


10. Применяем полисер на интерфейс. На логический интерфейс unit 1000 применяем полисер с важным голосовым трафиком. На второй логический интерфейс unit 2000 применяем первый полисер, который обрабатывает любой трафик как Best-Effort.

interfaces {
xe-7/0/0 {
unit 1000 {
family inet {
filter {
input {
UNTRUSTED_SUBSCRIBER_MF_CLASSIFIER;
}
}
}
}
unit 2000 {
family inet {
filter {
input {
UNTRUSTED_SUBSCRIBER_BLEACH_CLASSIFIER;
}
}
}
}
}
}

Я думаю, что всем должно быть ясно, что в одном вшивеньком посте нельзя рассказать даже и 1/10 всей информации по QoS. Однако именно этот пост был бы полезен мне в тот момент, когда я начал пытаться осмысливать концепцию Качества обслуживания. Возможно, кому-то ещё он тоже окажется полезен.

3 комментария: