Механизмы Quality of Service: управление трафиком при перегрузке, классификация, маркировка и дисциплины очередей.
Что такое QoS с точки зрения управления трафиком?
Чем полисинг отличается от шейпинга?
Какую проблему вызывает Tail Drop?
Какие поля используются для маркировки трафика QoS?
Когда QoS действительно необходим?
Еще один говорильный модуль, который у нас есть в рамках нашего курса, помимо того, что был только что про VPN-ы, это модуль, посвященный Quality of Service. И модуль этот говорильный, в том числе и потому, что практику на него сделать просто не получится. Дело в том, что настройки Quality of Service на железках разных производителей, разных линеек, и иногда даже в пределах одной линейки будут различаться. Поэтому мы с вами пройдем кратенько какие-то общие моменты, которые связаны с Quality of Service, и сойдемся на том, что настраивать все это дело, если нужно, то нужно будет смотреть просто документацию на конкретную железку, как оно там делается. Для начала давайте подумаем, что было бы, если бы у нас был просто провод. В одном проводе передается трафик между двумя абонентами. Нужно ли там было бы использовать какие-то механизмы Quality of Service?
Нет. Все, что передается по проводу, точно дойдет до другого конца, и задачи как-то управлять качеством передачи данных в одном проводе нет. Если у нас есть пакетная сеть, мы отправляем пакеты на какую-то транзитную железку, а она собирает трафик разных пользователей и начинает передавать этот трафик в сторону сети назначения по какому-то одному разделенному каналу, то тогда у нас есть вероятность того, что кадр, который мы отправим, или пакет, который мы отправим, будет потерян. И здесь у нас есть проблема, которая заключается в том, что мы иногда не хотим, чтобы определенный трафик терялся. Можем ли мы добиться того, чтобы трафик не терялся вовсе? Нет, не можем. В любом случае у нас есть вероятность того, что в какой-то момент буферы случайно окажутся перегруженными, и трафик теряться будет все равно. Но при этом мы с помощью специальных механизмов можем контролировать, что конкретно будет теряться. Если мы хотим, чтобы трафик определенных приложений не терялся,
мы можем указать, что трафик других приложений в этом случае теряться может с большей вероятностью, чем какой-то наш важный и приоритетный. Какие классические проблемы встречаются в пакетных сетях? Первая проблема — у нас есть, например, роутер, у него есть три гигабитных интерфейса, и трафик на двух гигабитных интерфейсах на роутер приходит и должен выйти через один. Понятное дело, что математика запрещает подобные вещи, она запрещает два гигабитных потока выпускать через один гигабитный интерфейс. Придется пакеты терять. Если мы хотим, чтобы трафик определенных пакетов терялся, а других не терялся, то мы можем разметить каким-то образом правила, по которым ненужные пакеты должны теряться с большей вероятностью, нужные — с меньшей. Может быть такое, что мегабитов-то и не будет не хватать. Может быть такое, что у нас просто случайно пришло одновременно много пакетов,
и нам нужно с этими пакетами как-то разобраться. 48 гигабитных интерфейсов, на 47 приходят пакеты, и все они адресованы в сторону одного выходного интерфейса. Они все должны быть положены в буфер. Мегабитов там немного, всего по одному пакетику пришло. Но буфер переполнился из-за того, что он маленький, случился так называемый микроберст, и в итоге некоторые пакеты в этом случае все равно могут быть потеряны. Это все классические проблемы для пакетных сетей. С ними можно будет бороться. Классическая настройка железок по умолчанию заключается в том, что никакой логики специальной для обработки пакетов нет. Все пакеты обрабатываются одинаково. Логика будет называться best effort, все пакеты одинаково обрабатываются максимально хорошо. Если есть возможность пропустить какие-то пакеты, такая возможность используется для доставки трафика. Мы делаем все, что от нас зависит,
для того, чтобы трафик доставить. Но если у нас не получается это сделать, логика best effort говорит: ну ладно, не получается, что же делать. Скидываем его. Что касается некоторых приложений, они из-за логики best effort будут страдать. Телефония, видеоконференц-связь, особенно высокой четкости, будет страдать от этого сильно, потому что при любой потере пакетов, при любой перегрузке в сети что у телефонии, что у видеоконференц-связи, особенно у видеоконференц-связи высокой четкости, сразу начинаются артефакты. Поэтому для того, чтобы разные приложения у нас могли сосуществовать в рамках одного и того же канала, в рамках одной и той же сети передачи данных, мы можем трафик разных приложений разметить неким специальным образом и сказать, что если у нас где-то в сети возникает перегрузка, то важные приложения мы не выбрасываем,
а неважные приложения мы, если есть перегрузка, если мы не можем доставить весь трафик, то трафик неважных приложений мы будем выбрасывать. Мы не будем ничего выбрасывать, пока у нас есть возможность профорвардить все. Но если возникает недостаточность ресурса и возникает необходимость чего-то выбросить, то выбрасываются в первую очередь неважные приложения. Quality of Service — это все про то, в какой последовательности мы будем угнетать приложения при необходимости. Если у нас есть возможность все профорвардить, форвардим все. Если у нас нет возможности профорвардить все, кем-то придется пожертвовать. Quality of Service — механизмы определяют, кем мы будем жертвовать. Механизмы Quality of Service будут состоять из нескольких разных механизмов. Первый механизм — это классификация и маркировка трафика. На основании неких признаков сетевые устройства должны будут принимать решение, что с конкретными кадрами делать:
их форвардить или их сбрасывать в случае перегрузки. И классификация, и маркировка как раз будут позволять такое решение принимать. Контроль полосы — это полисинг и шейпинг. И последующая ремаркировка — это механизмы, когда мы проклассифицировали трафик и дальше с ним что-то будем делать. Мы его будем либо пропускать дальше, либо немножко задерживать и пропускать дальше, либо дропать. Ну и последнее — это управление очередностью, шедулинг и кьюинг — это механизмы, когда у нас есть трафик разных приложений, и нам нужно, допустим, сначала отправить трафик более приоритетный, а потом менее приоритетный, что в такой ситуации делать. Это про очереди. Здесь у нас есть картинка. На этой картинке стоит какой-то подозрительный пунктир со словом «trusted domain». Логика будет вот какая. Когда мы отправляем трафик разных приложений, мы должны будем указать, что трафик этот действительно будет разный,
что у нас есть трафик более важный, трафик менее важный, трафик, который надо обрабатывать в одной логике, в другой логике. И обычно мы своим пользователям не доверяем, когда они проставляют какие-то указания, насколько доверенный или недоверенный будет определенный трафик. Но в некоторых ситуациях пользователю доверять можно, если мы знаем, что машина, которая проставляет указания, важно или не важно это будет трафик, она достаточно доверенная, что пользователь не может расставлять метки произвольным образом. Но чаще всего это не так. Чаще всего, если мы говорим про предприятие, у нас есть пользователи, которые просто подключаются к сети, они отправляют просто самый обычный трафик. Дальше, часто эти пользователи втыкаются либо напрямую в порт свитча, либо через телефон втыкаются в порт свитча. И здесь у нас возникает проблема, что пользовательский трафик у нас бегает одним образом, телефонный трафик в этом же порту у нас бегает другим образом. И нам нужно будет различать телефонный трафик и пользовательский трафик.
Поэтому телефон мы заставляем проставлять метки. Мы указываем, что у нас есть пользовательский трафик. Он идет просто обычными кадрами. А телефонный трафик — свои кадры телефон будет отправлять в 802.1Q Voice VLAN. И при отправке 802.1Q тегированных кадров у нас там есть замечательное поле 802.1P с тремя битами. И в эти три бита можно вписать разные значения приоритета. Этим битам приоритета, проставленным телефоном, мы будем верить. Обычному компьютеру мы ничего не доверяем, а телефону мы верим. Мы говорим, что телефон проставил метку 802.1Q, в этой 802.1Q метке три бита приоритета. Для обычного пользовательского трафика там стоит ноль, для телефонного трафика там стоит например 5. И соответственно на этом порту мы говорим, мы доверяем тому, что проставил телефон. На этом порту мы ничего не доверяем. Мы говорим, все, что приходит на недоверенном порту,
оно никоим образом не обрабатывается каким-то специфическим образом. А то, что приходит на этом порту, это уже доверенные метки, которые мы смотрим, которые мы умеем проверять, поэтому указанию того, как размечен трафик, здесь можно верить. Равным образом этот свитч, когда будет пропускать через себя такие кадры и пакеты, тоже будет доверять маркировке, которую проставил телефон. Или, может быть, мы сделали ремаркировку, может быть, мы на этом свитче проставили другие какие-то метки, но в любом случае это будут доверенные метки, и мы поверим тому, что там будет написано. В пределах этого самого домена меток вы будете доверять всем классификаторам, которые вы используете для определения того, важный трафик или неважный. Важно то, что этот домен Quality of Service должен быть неразрывным, что у вас не должно быть такого, что на какой-то транзитной железке железка не доверяет этим самым меткам и проставляет их по своему усмотрению. Не в той же самой логике, что на всех остальных узлах. И не должно быть такого, чтобы у вас на какой-то железке эти метки полностью игнорировались. Потому что если вы проставляете механизмы Quality of Service в сети, то они у вас должны работать от края до края. Все узлы в цепочке у вас должны руководствоваться одной и той же логикой обработки данных.
На границе этого самого trusted domain у нас, как правило, будет порт, на который подключается недоверенный узел. Понятное дело, что со стороны абонента будет такой порт. Если мы говорим про сеть предприятий, это тот порт, на который смотрит конечный компьютер. Плюс к тому есть порт, который смотрит в интернет. На нем тоже граница нашей ответственности заканчивается. Все, что мы отправляем в интернет, оно все равно может потеряться уже независимо от нас. Что бы мы ни делали, как бы мы ни расставляли метки, никто нашим меткам просто не поверит. Давайте разберем те механизмы, которые у нас есть в рамках Quality of Service. Первый — классификация и маркировка. Это два разных механизма. Они в какой-то степени похожи друг на друга и связаны между собой, но это все-таки две разные вещи. Классификация может выполняться по совершенно любым признакам в кадре. Может выполняться по признаку «кадр пришел из определенного порта», «кадр пришел с наличием 802.1Q метки», «кадр пришел с 802.1Q меткой» и там у него 802.1P написано 0 или 5.
«Кадр пришел, содержащий IP-пакет с вложением TCP, идущий на какой-нибудь порт». Вы можете на самых разных признаках принимать решение, что это за трафик. Классификация — это когда вы говорите: мы выделяем несколько типов трафика, несколько классов трафика. У нас есть класс, например, Voice over IP. У нас есть класс торренты. У нас есть класс веб-трафик, просто обычный серфинг веб-страниц. У нас есть класс бизнес-приложения, всякие 1С-ки и прочее. И по разным классам трафика мы раскладываем приходящие пакеты. Мы говорим: вот этот пакет посмотрели, ага, это 1С-ка. Мы сделали такой вывод на основании того, что там TCP с конкретным портом. Мы говорим, ага, это значит 1С-ка, соответственно, этот класс business critical. Дальше на следующий посмотрели, сказали, ага, допустим, протокол FTP, значит, это класс веб.
На следующий посмотрели, сказали, ага, там RTP-шное вложение, мы говорим, что это будет Voice. И на основании этих признаков мы раскладываем трафик по классам. И этих классов у нас ограниченное количество. Классификация — это именно когда мы посмотрели на конкретный кадр и приняли решение, к какому классу этот трафик относится. Маркировка — это механизм проставления таких признаков. Смысл заключается в том, что если у нас есть конечный абонент, он отправляет просто какие-то IP-пакеты, содержащиеся в кадрах, и там есть указание, что внутри лежит, номера портов TCP, UDP, но их анализировать, как правило, довольно долго. И заставить какой-нибудь слабенький свитч, который у вас на самой границе сети, анализировать, какие у вас там порты UDP, содержащиеся в IP-пакете, содержащемся в кадре Ethernet, может быть немножко негуманно. Потому что через этот свитч проходит достаточно много трафика. Весь этот анализ делается центральным процессором.
Поэтому заставлять анализировать, что внутри лежит — четные, нечетные порты для RTP-трафика — может быть очень тяжело. И принимать решение, что кадры содержат Voice over IP, на транзитном свитче по признаку «внутри кадра лежит IP-вложение, внутри IP-вложения лежит UDP-вложение, внутри UDP-вложения лежат четные номера портов», это просто очень тяжело для него, это неподъемная задача, он с такой задачей не справится. Но мы можем сказать: давайте мы будем использовать, например, 802.1Q-шный транк, в котором есть 802.1P-шная метка, и ее читает любой свитч практически на аппаратном уровне, и мы туда можем записывать три битика. И в эти три битика можем вкладывать разные значения, 8 разных значений от 0 до 7. И давайте мы на основании этой метки будем принимать решение, что важное, что неважное. Отправитель, понятное дело, эту метку вряд ли ставит, но мы можем заставить кого-нибудь в нашей доверенной сети проставлять такую метку на входе в сеть.
И дальше весь остальной путь трафика будет осуществляться достаточно легко, потому что на всех транзитных узлах мы будем ориентироваться уже на эту маркировку, которую какой-то доверенный узел за нас выполнил. И дальше на основании этой маркировки решение о том, что внутри лежит, принимается очень легко. На самом деле это очень простая штука. Если у вас, опять же, есть, например, компьютер, который подключается к телефонному порту, это у нас телефонный аппарат, который подключается к свитчу. Телефону мы верим, кадры, которые отправляет компьютер — просто самые обыкновенные кадры, телефон на них проставляет 802.1P-шную метку 0, что это неважный трафик. А дальше сами телефонные кадры отправляются с 802.1P-шной меткой, что это кадр, допустим, содержащий голос, проставляется пятерка во вложении 802.1P. И транзитный свитч
уже легко может на основании метки, до которой ему легко добраться — она в самом начале кадра расположена, там не надо раскрывать IP-вложения, не надо рассматривать UDP-вложения — он сразу по заголовку Ethernet, модифицированному транковому, может принять решение, кадры важны или неважны. Это намного проще делается, это можно сделать без привлечения центрального процессора, это можно сделать за крайне маленькое время. Соответственно, получается, что если мы такую штуку делаем, то свитчу это делать ненапряжно. И дальше этот свитч может передать кадр куда-то дальше, например, на роутер. И на роутер кадр мы, может, передадим, может быть, даже с той же самой 802.1P-шной меткой, но роутер дальше должен будет передать этот пакет куда-то еще, где 802.1P-шной метки нету. И он должен будет сказать: я хочу тебе сообщить, что это класс Voice over IP, но я не могу воспользоваться 802.1P, потому что этот канал вообще не Ethernet-овый, там 802.1P-шных меток нету, там какой-нибудь ADSL.
Или PPP, или что-то еще. Поэтому мы должны будем перемаркировать этот кусочек данных. Мы должны будем на уровне роутера раскрыть, обнаружить там внутри IP-пакет, а в IP-пакете у нас есть, например, метка Type of Service. И мы можем туда написать какое-нибудь значение, которое будет как раз обозначать, что внутри лежит Voice over IP. То, что мы в этом случае будем делать, будет называться ремаркировка. Мы определили, что трафик относится к определенному классу на основании одной метки или одного признака. И дальше мы сказали, что мы хотим отправить этот кусочек данных дальше по сети, но мы не можем сохранить те метки, которые у нас есть, или мы не хотим сохранять их. Мы должны будем перемаркировать трафик, чтобы следующий сосед цепочки понял, к какому классу относится этот трафик. Соответственно, место, куда можно было бы записать информацию о важности или неважности трафика, в принципе, в пакете есть несколько. Во-первых, если мы говорим про 802.1q, то это Priority Code Point.
Те самые три битика или восемь разных значений. Иногда эту штуку называют Class of Service. Более правильно называть Priority Code Point. Есть бывшее поле Type of Service в IPv4, которое потом разделили на DSCP и ECN. DSCP — это шестибитовое поле, в котором можно будет указать пять бит важности трафика. Можно будет воспользоваться предыдущей логикой, которая сейчас считается устаревшей. Это логика IP Precedence, когда из этого самого поля Type of Service три битика первых отводятся под указание важности трафика, а всё остальное там зарезервировано. Можно будет сказать, что у нас есть IPv6, и там тогда та же самая логика будет, либо DSCP, либо IP Precedence. Но тут уже будет не Type of Service называться, а Traffic Class. Смысл от этого не изменится, но название изменится. Можно будет ориентироваться не на маркировки, которые проставляет наше собственное оборудование, а можно ориентироваться на то, что по факту там внутри лежит.
Можно будет сказать, что если мы видим TCP или UDP вложение на определённые порты, это будет характерно для определённого трафика. Допустим, видим TCP или UDP 5060 порт. Ага, это SIP. Это сессионный протокол, который нужен для управления телефонией. Значит, мы можем его каким-то образом классифицировать в Voice over IP, и на основании этой классификации принимать уже дальнейшее решение о том, как такой трафик обрабатывать. Можно будет сказать, что мы не доверяем тому, что внутри написано. Если мы видим TCP 5060 порт, мало ли вдруг это злоумышленник какой-то пытается прикинуться SIP, а на самом деле он внутри HTTP гоняет. Можно в этом случае заставить этот роутер, например, если мы говорим про роутер, анализировать содержимое и смотреть, насколько содержимое TCP-шного потока похоже на SIP или не похоже на SIP. Может быть, он внутри увидит, что там на самом деле HTTP передаётся.
Поэтому можно будет заставить роутер анализировать содержимое передаваемых данных и говорить, что да, мы видим, что порты там какие-то кривые, но на самом деле внутри обычная HTTP-шная сессия. Эта штука будет называться NBAR, Network Based Application Recognition, если говорить про Cisco. Можно будет на основании просто IP-адресов принимать решение, что мы видим, пакеты идут на определённый IP-адрес или с определённого IP-адреса, и это уже само по себе неплохой классификатор. Это не классификатор, а маркировка, если хотите, на основании которой можно принимать решение о классификации. Классификация — это распределение трафика по классам, а маркировка — это механизм, с помощью которого мы упрощаем классификацию следующим узлам, чтобы они не занимались какими-то тяжёлыми вещами, а посмотрели бы на какую-то маркировку, которую мы проставили, и сразу бы ей доверяли. Так, дальше. Второй механизм, который здесь у нас будет, это управление полосой пропускания. Напрямую относится к Quality of Service,
потому что если у нас есть какой-то интерфейс, в который мы можем отправить данные, но в этом интерфейсе мы знаем, что данные дойдут до соседа, который нам не под контролем. То есть у нас есть наш домен Quality of Service, здесь есть граница, у нас есть роутер, и мы говорим, на роутер приходят наши пакеты доверенные, и мы хотим отправить их куда-нибудь, например, в интернет. Но в интернете мы не можем контролировать качество доставки, мы не можем на всех устройствах от края до края прописать политики Quality of Service. Но мы можем сказать, что, например, мы знаем скорость передачи данных в интернете. Мы взяли, померили эту самую скорость, выяснили, что от одного узла до другого некоторого узла мы хотим, допустим, туннель построить, GRE-шный. И мы знаем, что скорость передачи данных в этом GRE по факту не поднимается выше 2 Мбит в секунду. Мы можем в этом случае сказать, давайте мы будем ограничивать скорость в этом туннеле
таким образом, чтобы эта скорость по факту не превышала 2 Мбит в секунду. Например, ставим 1900 кбит. И тогда, если мы отправляем трафика не больше, чем 1900 кбит в секунду, трафик заведомо проходит через этот туннель. Заведомо проходит через все узлы и нигде не теряется, потому что мы нигде не создаём перегрузку сами. Как правило, для GRE-шных туннелей это не очень хорошо работает. Это хорошо работает для подключения к интернету, когда провайдер даёт вам какой-то тариф, сильно ограниченный по скорости. Например, он говорит вам, здесь у вас будет ADSL первого поколения. Он 8 Мбит на приём и 640 кбит на отдачу. Соответственно, если вы хотите отправлять в интернет какие-то данные, чтобы они не терялись, или терялись контролируемо, вы должны будете свою полосу зажать на скорости меньше, чем 640 кбит. Например, на 600 кбит. То есть надо будет именно строго меньше, чтобы было. Тогда вы, отправляя 600 кбит, не заставляете роутер провайдера отбрасывать ваш трафик на приёме. И тем самым вы говорите, что мы можем сделать так,
чтобы мы при попытке отправить пакет в этот самый интерфейс, в сторону провайдера, в ADSL интерфейс, какими-то манипуляциями добивались того, чтобы скорость средней отправки данных не превосходила некоторые заранее заданные нами скорости. Но есть нюанс. Интерфейс работает на строго фиксированной скорости. То есть есть у нас гигабитный интерфейс. Этот гигабитный интерфейс работает ровно на одной единственной скорости в 1 гигабит в секунду. 1 миллиард бит в секунду. 1 битик за одну миллиардную секунды. Не больше, не меньше. То есть не миллиард и ещё чуть-чуть, не миллиард без чего-нибудь. 1 битик передаётся ровно за одну миллиардную секунды. Если вы хотите передавать трафика меньше, чем миллиард за секунду, вы можете единственное, что сделать, это отправлять меньше битиков. Соответственно, вы в течение некоторого времени будете передавать эти битики, а в течение некоторого другого времени вы будете молчать, и средняя скорость у вас таким образом будет падать. Физическая скорость, line rate,
это 1 гигабит в секунду, без каких-либо исключений. Но если мы немножко передаём данные, немножко помолчим, немножко передаём, немножко помолчим, то получится, что средняя скорость у нас по факту будет пониже. Точно так же вы можете управлять полосой пропускания. Вы можете сказать, какой процент времени в среднем вы будете не разрешать отправлять кадры в интерфейс, для того чтобы средняя скорость получалась поменьше, чем разрешённая вам. Каким образом можно будет не отправлять данные в интерфейс? Мы всё говорили, как сделать так, чтобы данные отправлялись. Как прописать маршрут, и как заставить роутер делать то и это. Quality of Service говорит, как не отправлять данные. То есть если у нас есть интерфейс, который смотрит на провайдера, и интерфейс ADSL, в нём максимум мы можем отправить 600 кбит в секунду. Но при этом на ADSL канал, здесь у нас модем. Этот модем с одной стороны будет Ethernet,
а с другой стороны уже ADSL. Но мы сюда отправляем обычные Ethernet-овские кадры, и мы сюда можем отправлять на скорости в 1 гигабит в секунду. А дальше модем это всё будет уже преобразовывать и будет дальше передавать на скорости сильно меньше, чем этот самый гигабит. Мы должны будем в этот интерфейс не отправлять трафика больше, чем нам нужно. А иногда очень сильно хочется. Нам с одной стороны пришёл гигабит трафика, мы очень хотим гигабит сюда напихать. Но понимаем, что если мы сейчас гигабит туда напихаем, модем захлебнётся и будет отбрасывать трафик по своему усмотрению. Он будет полностью и тотально игнорировать то, как мы там занимались раскраской трафика, маркировкой, классификацией. Он будет отбрасывать трафик по признаку «оно просто не влезло». Неважно, что там внутри. Но мы можем сказать, давайте мы здесь будем контролировать, что мы запихиваем в этот интерфейс. Мы запихиваем в этот интерфейс трафика не больше, чем средняя скорость 640 кбит в секунду. И в этом случае мы говорим, трафик голосовой проходит без ограничений,
трафик, например, торрентов проходит только, если у нас остаётся свободная полоса пропускания. При этом возникает вопрос, а что сделать с остальным? Если к нам приходит гигабит, а нам надо пропихнуть 640 кбит, остальное куда девать? Остальное, понятное дело, придётся выкинуть. Но тут возникает вопрос, а если прямо сейчас трафик приходит на скорости в 1 гигабит в секунду, может быть, он через микросекунду прекратит приходить? Может быть, он прямо сейчас приходит на гигабите, а потом помолчит? Он снова будет приходить, он снова будет молчать. Поэтому средняя скорость, на которой данные приходят к нам, мы вообще никак контролировать не можем. Он прямо сейчас приходит, а может быть, через секунду перестанет приходить. Поэтому есть два механизма, которые здесь будут работать. Первый механизм будет называться полисинг. Он заключается в том, что если трафика у вас приходит больше, чем надо, и вы понимаете, что у вас есть интерфейс, в который вы можете в среднем отправлять 640 кбит в секунду, и к вам приходит кадр, который вы отправить не можете, потому что если вы попытаетесь его отправить,
у вас средняя скорость будет 641 кбит в секунду. Полисинг заключается в том, что вы такой кадр выбрасываете. Просто без каких-либо сожалений. Фактически это будет означать, что если у вас средняя скорость по такому графику устроилась на входе на интерфейс, то на выходе вы получите с полисингом вот такое. То есть все эти верхушки выше некоторой фиксированной скорости вы будете отбрасывать. За счёт того, что кадры, которые попадают в эти верхушки, вы просто выбрасываете целиком. Полисинг — это очень жёсткий механизм, но, в принципе, созвучно, да, полисинг, полиция. Она обычно не церемонится ни с чем. И да, в некоторых ситуациях полисинг — очень хорошая штука. Если мы говорим про какие-то протоколы, которые не терпят дополнительных задержек, голосовые всякие приложения и прочее, то полисинг на самом деле — это вполне разумный механизм. Если у нас есть голосовые кадры, нет смысла с ними что-то делать, кроме как их выбрасывать. Если мы не можем их отфорвардить прямо сейчас,
то ничего с ними не сделаешь, выкидываем, они всё равно протухнут. Следующий кадр, который придёт, он будет уже содержать более актуальную информацию. Но в некоторых случаях иногда выгоднее получается придержать такой кадр. Если у нас есть средняя скорость приходящих кадров, которая используется, у нас есть какая-то скорость, средняя скорость до достижения некоторого максимального значения, которое мы сказали, что будет разрешено, например, здесь 640 кбит в секунду, у нас начинает приходить кадр. Один кадр пришёл, средняя скорость маленькая. Второй кадр пришел, средняя скорость тоже маленькая. Третий кадр пришел, крошечный. Средняя скорость все еще не превышает достижимой. Четвертый кадр пришел, тоже средняя скорость пока еще нормальная. Пятый пришел, вроде все еще хорошо. Следующий, шестой пришел, уже вылез за пределы достижимого. Если бы полисинг использовали, мы бы сказали, нет, мы такой кадр не форвардим дальше. Если бы мы использовали полисинг, мы бы его выкинули,
а если мы будем использовать другой механизм, который называется шейпинг, то мы этот кадр откладываем в буфер. И мы ждем, ждем, ждем, ждем, ждем некоторое время. И когда средняя скорость, которую за последний некий период мы намерили, позволит нам этот кадр отправить, мы его отправляем. И, соответственно, он у нас отправляется с некоторой задержкой. Шейпинг позволяет более эффективно использовать полосу пропускания. Если у вас такие кратковременные всплески случаются, вы просто их откладываете во времени, позволяете все равно отправить, но при этом откладываете доставку трафика. Это неконтролируемо влияет на задержки при прохождении пакетов по сети. Поэтому если вы используете этот механизм для VoiceOver IP или чего-то еще, то VoiceOver IP, конечно, будет страдать от этого. Надо аккуратно разделять трафик ваших клиентов по различным очередям и говорить, что для определенных классов трафика лучше использовать полисинг, для определенных классов трафика лучше использовать шейпинг.
И опять же, нет никакого правила, которое заставляет вас работать только каким-то одним образом. Из каждого правила есть исключение. И вполне может быть такое, что в конкретно вашем случае VoiceOver IP может быть имеет смысл шейпить. Различия между полисингом и шейпингом я уже вам объяснил. Полисинг обычно вешается на приеме. Если у нас есть роутер, и у него есть входящий и исходящий интерфейс. Соответственно, для входящих кадров имеет смысл просто сразу делать полисинг, что больше, чем определенные значения, больше, чем определенная скорость от этого интерфейса, мы в принципе не готовы получать. Чаще всего, как провайдеры, когда они подписывают с вами контракт, они говорят вам, я тебе продам интернет 50 мегабит за 500 рублей. Они говорят, я тебе продам 500 мегабит. Фактически они говорят, я тебе повешу полисер на интерфейсе, который будет все, что выше 50 мегабит, пристреливать. Полисинг хорош тем, что он не вносит никакую дополнительную задержку,
но если у вас есть TCP-шные сессии, которые работают с полисингом, бывает так, что они не очень хорошо себя ведут. В зависимости от разных условий у конкретной реализации TCP может очень неоптимальная вещь происходить. Может быть такое, что TCP себя будет вести неоптимально, если его пристреливать с помощью полисинга. Поэтому, если вы хотите, чтобы у ваших клиентов проблем с TCP было меньше, то вы можете использовать шейпинг. Шейпинг обычно вешается на выходе. Мы говорим, что у нас здесь есть некая законтрактованная скорость, и мы должны соблюдать эту скорость, поэтому мы здесь делаем специальный буфер для тех кадров, которые надо отправить по сети, но прямо сейчас мы их отправить не можем. Поэтому, когда приходит какой-то кадр, мы его кладем в этот буфер, дальше из этого буфера он по мере необходимости отправляется. Этот буфер будет уже не стандартным буфером на интерфейсе. Обычные буферы интерфейсов — они маленькие. А этот буфер будет отдельный, выделяться в оперативной памяти.
Чем у вас больше клиентов, которые будут использовать шейпинг, тем, соответственно, у вас будет все больше и больше памяти отжираться под эти самые очереди. Неприятности у шейпинга заключаются в том, что вносится непредсказуемая задержка. Соответственно, в VoiceOver IP сразу возникает вопрос, насколько хорошая идея использовать шейпинг. Но зато TCP себя чувствует с ним намного лучше. TCP будет намного легче понять, что у вас есть какая-то задержка, которая, возможно, плавает при передаче данных по сети, чем испытывать проблемы из-за того, что у вас данные просто теряются. Еще одна штука, которая будет связана с Quality of Service, это управление очередью. И здесь, опять же, у нас два механизма. Первый — это queuing, когда у нас есть несколько очередей, в которые можно положить пакет. И второй — это scheduling. Это когда у нас есть несколько очередей, из которых мы можем забрать пакет для того, чтобы отправить данные дальше в сеть назначения. Смысл заключается в том, что если у нас есть,
например, картинка, как здесь, у нас есть один интерфейс, и дальше на этом одном интерфейсе мы должны выплевывать трафик, который приходит по двум входящим интерфейсам. К нам приходят какие-то кадры, некоторые из них важные, некоторые из них неважные, и мы должны будем принимать решение, как эти кадры должны будут обрабатываться. Например, этот кадр у нас неважный, и этот кадр у нас неважный, а этот кадр важный, и этот кадр важный. Мы, например, по какому-то критерию можем это определить. Например, самый простой критерий, что все, что приходит из нижнего порта, — все очень важное. Если мы будем обрабатывать все это дело в логике best effort, то этот пакет придет самый первый, он в сеть назначения уйдет самым первым. Этот пакет придет вторым, мы его отправим вторым. Этот пакет придет третьим, мы его отправим третьим. И этот пакет придет четвертым, мы его отправим четвертым. Это стандартное поведение best effort, в каком порядке пришло, в таком порядке ушло. Еще иногда называется FIFO, first in, first out. Или обычная очередь. Если же мы хотим, чтобы у нас работали механизмы
quality of service, и эти зеленые пакеты обрабатывались максимально приоритетно по сравнению с остальными, то нам придется немножко постараться и правильно, корректно расставить очереди. Первый пакет, который придет, он безусловно придет самый первый, он безусловно попадет в очередь, какая бы там ни была очередь, он безусловно будет отправлен в сеть назначения самым первым. Потому что нельзя сделать так, чтобы пакет, который пришел вторым, вклинился бы перед пакетом, который пришел первым. Этот пакет пришел, занял, запустил процедуру маршрутизации и был отправлен в сеть назначения. Но интерфейс, который отправляет эти данные, он, соответственно, немножко уже занялся. У нас здесь сейчас прямо происходит процедура отправки этого пакета. Приходит второй, более важный пакет. И нам нужно сделать так, чтобы второй, более важный пакет отправился бы максимально быстро, насколько это вообще возможно. Мы его ставим, соответственно, в очередь на доставку, в общую очередь.
Соответственно, это пакет первый, этот пакет будет на втором месте. Если мы будем ставить этот пакет в ту же самую очередь, то тогда, когда придет третий пакет, мы этот третий пакет тоже должны будем поставить в ту же самую очередь. У нас получится первый, второй, третий, четвертый. Первый, второй, третий, четвертый. Вот он третий, вот он второй, вот он четвертый. И получится, что этот важный четвертый пакет в итоге мы не сможем отправить более быстро, чем, например, третий. В каком порядке они пришли, в таком порядке они ушли, это то же самое, что мы в итоге получили. Но если мы скажем, что пришел первый пакет, мы его кладем в неважную очередь, потому что он неважный. Приходит второй пакет, мы его кладем в важную очередь, и первый пакет начинает отправляться по сети первым, но, соответственно, сам чип, который отправляет данные, он сейчас прямо загружен. Но следующий пакет, который будет забираться, он будет забираться как раз второй пакет, он в следующей очереди. Следующий в другой очереди, в более приоритетной. Когда приходит третий пакет,
мы его ставим в неважную очередь, и когда приходит четвертый пакет, мы его ставим в важную очередь. Это первый, второй, третий, четвертый. И механизм, как разложить трафик по приоритетным очередям, это как раз queuing, когда у нас есть две разные очереди, одна более важная, другая менее важная. И после того, как мы трафик проклассифицировали, приняли решение, куда его девать. Queuing — это как раз из двух очередей, важной и неважной, мы для каждого кадра выбрали более подходящую для него. А дальше начинает работать scheduling. Когда этот маленький чипчик, который отправляет кадры в интерфейс, он превращает кадры из очередей собственно в битики, в нолики, единички. Он говорит, я сначала забираю трафик из приоритетной очереди, и только когда приоритетная очередь пустая, я забираю трафик из неприоритетной очереди. Этот механизм будет называться scheduling. То есть как мы освобождаем очереди. Queuing — как мы заполняем очереди, scheduling — как мы освобождаем их. В терминах Cisco у нас есть следующие страшные буквы,
которые нужно будет посмотреть, убедиться, что вы испугались их. И на экзамене вряд ли вас будут спрашивать про них, но тем не менее надо примерно представлять, что такие буквы вообще встречаются. Самый простой тип очередей — это приоритетный queuing. Когда у вас есть сверхприоритетная очередь, до тех пор, пока она не освободится, к другим очередям, соответственно, scheduling не приступает. Она же называется low latency queuing, потому что если кадр попадает в такую приоритетную очередь, то его задержка минимизируется за счет того, что такая очередь быстрее всех освобождается. Это, если хотите, такая выделенная полоса для голосового трафика. Low latency queuing или priority queuing, или LLQ или PQ. У такого механизма scheduling есть проблема. И проблема заключается в том, что если у вас приходит слишком много приоритетного трафика, то неприоритетный трафик откладывается сильно далеко.
И может быть такое, что за счет того, что прибежало одновременно слишком много приоритетного трафика, неприоритетный трафик откладывается при отправке во времени на миллисекунду. Или на 2 миллисекунды. Или на 10 миллисекунд. Чем больше у вас буфера, тем, соответственно, больше он может быть отложен. И при определенных обстоятельствах это может действительно вызывать очень большие проблемы. Если бы у нас было всего 2 очереди, ладно, это ничего страшного бы не было. Голосового трафика никогда не бывает столько, чтобы задержка при передаче данных становилась бы слишком большой. Но если у нас этих самых классов и очередей много, например, 10. 10 очередей, которые может scheduler освобождать по какому-то признаку. Получится, что мы же не можем сказать, давайте сначала освобождать эту, потом эту, потом эту. Мы должны будем каким-то образом постепенно разбирать все очереди. А не так, что если у нас приходит много-много трафика в эту очередь и много-много трафика в эту,
и в эту, и больше, чем у нас вообще всего очередь на отправку есть, то до этих всех вообще никогда даже очередь не дойдет. Мы должны будем постепенно освобождать очереди все, независимо от того, насколько они важны или нет, просто делать это с разной скоростью. Механизм, который будет называться fair queuing, FQ, он будет давать сравнительно честное освобождение очередей. Когда у вас есть много этих самых очередей, мы разбираем трафик из каждой по чуть-чуть и отправляем его в сеть назначения. Неважно, важный или нет. Неважно, приоритетная это очередь или нет. Соответственно, есть иногда желание сделать так, чтобы одна из таких очередей была более приоритетной, чем другая. Тогда мы можем сделать, например, следующую штуку. Сказать, что у нас есть 10 очередей, И одна из этих очередей будет иметь вес, например, 100, другая — вес 90, третья — вес 80, 70 и так далее. Вес будет указывать пропорциональность трафика, который мы будем забирать. Сначала забираем условно 100 байт
из одной очереди, потом 90 байт из другой, 80 из третьей, 70 из четвертой и так далее. Пробегаемся по всем очередям и потом снова начинаем освобождать все очереди по цепочке. Эта штука называется weighted fair queuing или WFQ. И ещё здесь можно будет учитывать класс трафика, это 802.1p или type of service или что-то ещё. Если вы хотите, вы можете сказать, что у нас, во-первых, очереди имеют веса, во-вторых, внутри каждой очереди есть ещё возможность, если вы напихаете в пределах одной очереди трафик с разными классами, с разными type of service или с разными 802.1p-шными метками, обращать внимание на эти метки тоже. И из очереди доставать трафик, соответственно, пропорциональный этим самым классам. Тогда эта штука будет называться CB-WFQ. Class-based weighted fair queuing — это наиболее честное распределение. Если вы выполнили классификацию трафика и voice over IP напихали трафик в одну большую очередь, поставили ей какой-то вес,
а дальше внутри этой очереди оказывается, что у вас есть трафик более приоритетный и менее приоритетный, тогда CB-WFQ заберёт трафик более приоритетный чуть с большей вероятностью, чем менее приоритетный. Всегда, когда у нас есть несколько очередей, это будет означать, что мы трафик будем ресеквенсить, что мы будем заниматься перестановкой пакетов. Трафик пришёл в одном порядке, а мы за счёт управления очередями отправляем его в другом порядке. Это неизбежное зло. Поэтому мы никогда не хотим делать так, чтобы трафик одного и того же приложения у нас распределялся по разным очередям. Ещё мы не хотим, чтобы у нас в очереди возникали перегрузки. Если у нас есть, например, интерфейс на роутере, и в этот интерфейс можно отправлять, допустим, 1 гигабит трафика. Может быть такое, что трафик, который придёт на наш роутер, его будет настолько много,
что этот гигабитный интерфейс, неважно, в каком порядке мы туда кадры засовываем, в правильном, в неправильном, он просто перегрузится. Понятное дело, что у нас здесь есть шейпер, например, есть механизм, который позволяет в буфер нагнать трафик. Но всё равно, если у нас постоянно приходит гигабитный поток здесь и гигабитный поток здесь, то математика запрещает делать так, чтобы у нас бесконечно много трафика на 2 гигабитах приходило на роутер и через 1 гигабитный порт выходило. Всё равно этот излишек куда-то должен скапливаться. Скапливаться он будет в этот буфер. Буфер не резиновый, рано или поздно он забьётся, и тогда у нас будет происходить что? У нас будет происходить явление, которое называется tail drop. У нас есть очередь на отправку данных куда-нибудь. Эта очередь заполняется целиком. Соответственно, новые пакеты, которые должны встать в хвост этой очереди, они не могут туда встать, и из хвоста очереди они просто выкидываются. Ничего другого с ними не сделаешь. Это единственное, что возможно. Это самый простой механизм работы с перегрузкой.
Сказать, что это механизм предотвращения перегрузки, конечно, будет грешновато. Это не предотвращает перегрузку. Когда перегрузка происходит, это неизбежное зло при работе с ней. Но механизм tail drop неприятен тем, что, во-первых, сбрасываться будут пакеты абсолютно невзирая на то, насколько они важны или не важны. Если у нас есть физический интерфейс, который отправляет данные на одном гигабите, то трафик, который приходит на этот интерфейс, будь он хоть трижды телефонный, он всё равно забьёт этот интерфейс целиком. И дальше все пакеты, которые будут приходить новые и новые телефонные, они всё равно будут отбрасываться, потому что всё загружено. Может быть такое, что мы насовали в буфер много-много торрентов, а потом хотим отправить один маленький телефонный пакетик, а там места нет. Неприятности. Более того, если у вас в буфере место кончилось и одновременно приходят много-много-много TCP-шных данных из разных TCP-шных сессий,
то все эти TCP-шные сессии одновременно получат потерю пакета. А когда TCP теряет пакет, он резко проседает по скорости. У него есть механизм управления скоростью, он управляет, во-первых, окном, во-вторых, он управляет тем, на какой скорости он отправляет данные. Если у нас одновременно прибежали три TCP-шных сегментика, попытались встать в очередь, и там их tail drop'нули, то мы будем наблюдать такую картинку, что на интерфейсе у нас было, например, три TCP-шных сессии, которые одновременно забивали интерфейс полностью. В какой-то момент у нас случился tail drop, и во всех трёх сессиях одновременно резко просела скорость. Соответственно, она просела, интерфейс освободился. Мы нагрузку-то создаём не абстрактную, не нагрузку в вакууме. Те же самые сессии создавали нагрузку. Соответственно, узлы, которые отправляли данные в этой TCP-шной сессии, поняли, что случился отказ, говорят, сейчас мы будем ретрансмитить, и ретрансмитить с потерей скорости. Дальше начинают ретрансмитить, с потерей скорости переотправляют потерянные данные,
говорят, нормально, всё пришло, давай дальше продолжай. Они некоторое время работают на пониженной скорости, потом говорят, вроде в последнее время потерь нет, давайте разгоняться. И они начинают снова разгоняться. Снова разгоняются, разгоняются, разгоняются, доходят до какой-то предельной нагрузки, снова случается tail drop, снова все три сессии проседают по скорости, и такая пила получается по эффективной утилизации канала. Очень такую штуку провайдеры не любят. Она выглядит как пила, и фактически здесь будет означать, что в эти моменты у нас стопроцентная утилизация канала, а в эти моменты у нас 70% утилизация канала. И происходит это за счёт того, что у нас в TCP во всех сессиях одновременно случается tail drop. Очередь забивается целиком, прибегают новые сегменты из разных сессий, они все tail drop'аются, и все одновременно падают в деградированное состояние. Штука эта называется TCP synchronization, когда разные сессии одновременно испытывают tail drop,
одновременно проседают по скорости, и у вас трафик на интерфейсе начинает скакать. Как с этой штукой, с синхронизацией TCP, бороться? Есть такой механизм, который называется random early detection. Заключается он в следующем. Если у нас есть несколько сессий, которые используют один и тот же интерфейс, мы можем не дожидаться tail drop'ов. Мы можем, начиная с некоторого момента, сказать: трафик, который забивает нашу очередь, забивает её слишком быстро. Если мы позволим буферу забиться на 100%, у нас будут tail drop'ы. Tail drop'ы неконтролируемые, вызывают синхронизацию, и вообще это плохо. Но есть нюанс. Если в этом буфере на отправку мы видим, что очередь растёт, растёт, растёт и достигла какого-то критического значения, но ещё нет tail drop'ов, например, она выросла до 50%, мы можем сказать: давайте мы будем неким произвольным образом
расстреливать случайно кадры, которые приходят в эту очередь, или пакеты, или сегменты, как хотите назовите. Если у вас очередь начинает расти и доходит до 50%, это значит, что интерфейс у вас 100% нагрузки уже висит, уже без дропов не обойтись. Но если мы допустим tail drop, то мы допустим tail drop для всех одновременно. А если мы случайно начнём расстреливать одиночные пакеты, то мы дропы будем вызывать не у всех сессий одновременно, а у разных сессий в разное время. Соответственно, мы дошли до 100% загрузки интерфейса, и у нас начинает расти буфер. Одну сессию мы расстреливаем, все остальные сессии работают на полной скорости. И она-то просела, но все остальные сессии нормально раскачиваются, раскачиваются, раскачиваются, и у нас пила получается существенно меньше, существенно глаже. После чего одну сессию пристрелили, загрузка упала там с 50% до 30%. Потом снова начинает расти до 50%. Снова мы случайным образом одну сессию — тыньк, булавкой,
шарик лопается у неё, но все остальные продолжают работать. Эта штука называется RED, Random Early Detection. У Cisco есть разновидность этого RED. Называется WRED, Weighted Random Early Detection. Хотя по-русски слово WRED означает что-то совсем другое, но на самом деле Random Early Detection — это очень полезная и реально полезная вещь. Она не вредная, она полезная. Заключается она в том, что мы в первую очередь кандидатов на расстрел будем выбирать, исходя из того, что трафик, который мы будем видеть, у него есть какие-то приоритеты. У него есть Type of Service, у него есть Class of Service, и мы можем смотреть на Class of Service. Если мы будем видеть, что там трафик какой-то левый, неважный, торренты, например, мы его будем расстреливать уже при очереди в 50%. А если мы будем видеть, что там трафик какой-то серьёзный, например, 1С, его мы будем расстреливать в последнюю очередь. И смысл WRED заключается в том, что мы всё точно так же расстреливаем случайным образом кадры,
которые в нашей очереди находятся, когда эта очередь ещё не заполнилась целиком, но у нас всё ещё место там есть. И для важных кадров это место остаётся, а неважные кадры мы из этой очереди выкидываем тогда, когда они создают какую-то угрожающую нагрузку. И тем самым получается, что мы намного более эффективно можем использовать наш канал. Рекомендуется к использованию, включается достаточно легко, если вы quality of service пользуетесь. Чаще всего используется, конечно, провайдерами. В предприятиях такая ситуация, что у нас есть интерфейс, на котором есть перегрузка со многими TCP-шными сессиями, встречается довольно редко. Это всё, что касается теории про quality of service. Я рассказал про механизмы, которые встречаются в QoS. Я ничего не рассказывал про то, как это включать, потому что включается на железках разных годов выпуска, разных линеек, естественно, разных производителей, абсолютно по-разному. Нет никакого стандартного механизма, как управлять quality of service. Кратко я вам рассказал про то,
что с quality of service не всё так легко. Нет какой-то универсальной кнопочки «сделать хорошо». В Spanning Tree, например, есть кнопка «Включи Spanning Tree», и он уже будет работать. Может быть плохо, но будет. В quality of service механизма такого универсального нет. Вы сами должны будете определять, где у вас границы домена quality of service, кому вы доверяете, кому вы не доверяете, как вы классифицируете трафик. По каким признакам вы определяете, что трафик будет одного или другого класса. Как вы маркируете трафик, чтобы следующим узлам в Trusted Domain у вас было попроще выполнять классификацию. Как вы управляете очередями, как вы управляете шедулером, который забирает трафик из разных очередей. Как вы тем самым перегрузками управляете. Всё это можно будет настроить на железках разных производителей. Как было сказано, абсолютно по-разному настраивается. И нужно ли вам это делать в вашей сети предприятия, вы должны будете принять решение сами. Настраивается, как правило, тяжело,
долго, пользу приносит только в ситуации, когда вы чувствуете, что трафик определённых приложений по сети проходит некорректно. Если вы попытались телефонию поднять, а все пользователи говорят: «Знаешь, плохо работает телефон. Булькает, всё шмулькает, бипы, плипы, пропадание голоса. Некомфортно пользоваться телефонией». В этом случае вам нужен QoS. Если вы в сети своей гоняете только какую-нибудь 1С, вам этот QoS не нужен, он без QoS будет прекрасно работать, 1С, ни на что внимания не обращая. Так что сказать, что всем надо поголовно quality of service настраивать, абсолютно нельзя. Многие сети работают прекрасно без QoS и, соответственно, проблем никаких не знают. Как правило, необходимость есть у тех, кто либо внедрил у себя IP-телефонию, и в сети есть какие-то значительные перегрузки, либо, если мы говорим про решения,
например, на основе TelePresence, они достаточно жручие, они могут использовать достаточно много полосы, и они крайне чувствительны как к потерям трафика, так и к перегрузкам. Поэтому, если у вас такая штука есть, вы, наверное, захотите использовать QoS. Как правило, да. В такой ситуации вам сам интегратор, который будет разворачивать решение TelePresence, намекнёт на то, что в вашей сети без этого нельзя. А поскольку штука довольно дорогая, то quality of service развернуть в такой сети можно будет достаточно легко и за сравнительно небольшие деньги по сравнению с общим решением. На сегодня, пожалуй, всё в смысле quality of service. Давайте этот модуль мы пока закончим. Продолжение следует...