Использование Hierarchical Fair Service Curve (HFSC) в OpenBSD

Опубликовано – 30.11.2009

Перевод: Сгибнев Михаил
Оригинал: Hierarchical Fair Service Curve (HFSC) of OpenBSD

 Качество в обслуживании (Quality of Service) (QoS) является попыткой организовать приоритезацию занных по типу пакета, передаваемого в рамках определенной сессии. Hierarchical Fair Service Curve поднимает QoS на более высокий уровень по сравнению с CBQ, сосредотачиваясь на гарантированной передаче real-time данных, адаптивной передаче данных best-effort и иерархическом разделении канала.

 Хотя данная тема может казаться трудной, но как только вы поймете основы, то она окажется действительно удобна в использовании.

 Если не использовать технические термины, то HSFC позволяет вам управлять исходящим от вашей системы трафиком. Например:

  • Вы можете помечать ack пакеты самым высоким приоритетом, чтобы гарантировать их отправку. Пакеты Ack посылаются удаленной системе в качестве подтверждения того, что вы получили отправленный ей пакет и готовы принимать следующий. Таким образом мы обеспечим максимальную производительность даже на
    загруженных линиях.
  • Если вы — отъявленный геймер, а другие пользователи вашей сети занимают весь канал своими ненужными данными. Вполне вероятно, что вы захотите повысить приоритет игрового трафика над обычным web трафиком. Таким образом вы сможете уменьшить задержки пока другие пользователи скачивают файли или бродят по Интернетам.
  • В случае, если у вас есть веб-сервер и вы определили, что большинство исходящих данных является обычным текстом и составляет меньше чем 10 КБ за страницу, но имеется несколько больших файлов, приблизительно по 5 МБ. У вас появилось желание организовать раздачу на максимальной скорости при подключении и снизить скорость через несколько секунд. Такое управление трафиком называют нелинейной кривой сервиса (NLSC или просто SC). С помощью HFSC, вы можете указать пакетному фильтру вести раздачу первые несколько секунд подключения на полной скорости, например 100KB/sec и затем замедлить подключение через 5 секунд до 25KB/sec. Это позволит вам отдавать html на полной скорости, а загружать 5 МБ файлы на медленной скорости, сохраняя полосу пропускания на других клиентов сети.

 Таким образом, Quality of Service дает вам средства управления трафиком.

 Внимание! Calomel.org так же предоставляет OpenBSD Pf Firewall «how to» ( pf.conf ), где содержатся примеры использования HFSC.

 

Основы всего (HFSC basics)

 Давайте посмотрим на основной набор команд HFSC и выясним, почему вы бы захотели использовать их в реальном мире:

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

  • В родительской «altq» строке определяется суммарная пропускная способность для всех очередей интерфейса. Указывается общая пропускная способность, предоставляемая провайдером и не зависящая от скорости сетевого интерфейса. Очень важно указать этот параметр чуть меньшим, чем максимальная пропускная способность канала, так как altq может ставить данные в очередь и не передавать на вышестоящий роутер. В данном примере это 96% от 1000kbit/sec.
  • В дочерней «queue» строке(ах) эта директива определяет максимальную скорость передачи информации в битах, которая будет обработана очередью в любой момент. Эта директива — фактически аналогична использованию «linkshare» с параметром (m2). Это значение не должно превысить значение родительской очереди и может быть определена как абсолютная величина или процент от полосы пропускания родительской очереди. Если значение не определено, то по умолчанию размер равен 100% полосы пропускания родительской очереди. Желательно назначить процент от вашей полной полосы пропускания каждой дочерней очереди, при этом не превысив суммарные 100% родительской очереди.

 priority: уровень, определяющий порядок, в котором сервис будет обслуживаться относительно других очередей. Чем выше число или значение, тем выше приоритет. Эта директива — простой способ указать, какие пакеты будут отправлены первыми, по сравнению с другими. Приоритет не задает полосу пропускания, но определяет порядок, в котором пакеты буферизуются перед отправкой. Например, у вас имеются игровые данные и web трафик. Так как игровой трафик является интерактивным, то его необходимо отправить в первую очередь, а web трафик может подождать, для этого установим очереди игровых данных приоритет выше, чем у очереди web трафика. Диапазон приоритетов для HFSC и cbq может принимать значения от 0 до 7, а для priq диапазон равен от 0 до 15. Приоритет 0 является самым низким приоритетом и назначается наименее важным данным. Если приоритет на задан, то в качестве значения по умолчанию используется 1 приоритет. Очереди типа Priq с более высоким приоритетом всегда обслуживаются первыми. Cbq и очереди типа HFSC с более высоким приоритетом обслуживаются первыми в случае, если канал выбран полностью, а полоса пропускания «realtime» также исчерпана.




 qlimit: количество «слотов», доступных для очереди, чтобы хранить отправляемые пакеты, когда количество доступной полосы пропускания для очереди было превышено. По умолчанию это значение равно 50. Когда на исходящем интерфейсе будет достигнуто максимальное значение полосы пропускания, или ее займут данные с более высоким приоритетом, qlimit поместит пакеты, которые очередь не может отослать, в память, занимая свободные слоты. Когда полоса пропускания будет доступна, qlimit слоты будут освобождены в том порядке, в каком они поступали (FIFO). Если qlimit достигнет максимального значения qlimit, то пакеты будут отброшены. Рассматривайте использование qlimit как крайнее средство, но это альтернатива отбрасыванию пакетов. Кроме того, не думайте, что qlimit действительно способен решить проблему проблему перегрузки полосы пропускания и отбросов пакетов. Данное средство предназнчено для кратковременного хранения пакетов в момент перегрузки канала.

 realtime: размер полосы пропускания, которая гарантируется очереди независимо от того, в какой полосе нуждается любая другая очередь. Данный параметр может быть установлен от 0% до 80% полной полосы пропускания. Можно сказать, что вы хотите быть уверенным в том, что ваш веб-сервер получает 25KB/sec полосы пропускания независимо ни от чего. Определение значения realtime даст очереди веб-сервера полосу пропускания, в которой она нуждается, даже если другие очереди хотят совместно использовать ее полосу пропускания.

 upperlimit: определяет количество полосы пропускания, которую очередь не может превысить. Например, вы устанавливаете почтовый сервер и хотите быть уверенным, что он не откусит больше 50% полосы пропускания, или у вас имеется активный пользователь p2p. Используя upperlimit можно будет препятствовать перегрузке канала.

 linkshare (m2): этот параметр имеет тот же самый смысл, как и «bandwidth», указанный выше. Если вы определите параметры «bandwidth» и «linkshare» в одном правиле, то pf (OpenBSD)будет использовать директиву «linkshare m2». Это может вызвать больше беспорядка, чем хотелось бы, если у вас есть два различных параметра настройки в каждом. По этой причине мы не собираемся использовать «linkshare» в наших правилах. Единственная причина, по которой вы можете захотеть использовать «linkshare» вместо «bandwidth», это использование нелинейной кривой сервиса (nonlinear service curve).

  • nonlinear service curve (NLSC or just SC): директивы «realtime», «upperlimit» и «linkshare» могут использовать в своих интересах NLSC. В нашем примере ниже мы будем использовать эту опцию на нашей очереди «web». В качестве параметров выступают переменные m1, d, m2, где m2 управляет полосой пропускания, назначенной на очередь. m1и d являются дополнительными и могут использоваться, чтобы управлять начальным размером полосы пропускания. Для первых d миллисекунд очередь имеет полосу пропускания m1, после чего принимает значение, заданное в m2.

 default: очередь по умолчанию. Все, что не попадает в другие правила — попадает сюда. Эта директива должна использоваться только один раз.
 

Формат очередей HFSC

 

 Давайте теперь разберемся с произвольным набором правил HFSC. Следующая группа правил разбивает наши данные на 8 групп, описывающие различные типы трафика и дает каждой из них определенную полосу пропускания. Вы не должны точно следовать этому примеру, тем более, что у вас есть все определения выше.

 Вы можете просто скопировать данный набор правил, так как он является полностью рабочим.

# Comcast Upload = 1000Kb/s (queue at 96%)
altq on $ExtIf bandwidth 960Kb hfsc queue { ack, dns, ssh, web, mail, bulk, bittor, spamd }
queue ack bandwidth 30% priority 8 qlimit 500 hfsc (realtime 20%)
queue dns bandwidth 5% priority 7 qlimit 500 hfsc (realtime 5%)
queue ssh bandwidth 20% priority 6 qlimit 500 hfsc (realtime 20%) {ssh_login, ssh_bulk}
queue ssh_login bandwidth 50% priority 6 qlimit 500 hfsc
queue ssh_bulk bandwidth 50% priority 5 qlimit 500 hfsc
queue bulk bandwidth 20% priority 5 qlimit 500 hfsc (realtime 20% default)
queue web bandwidth 5% priority 4 qlimit 500 hfsc (realtime (10%, 2000, 5%) )
queue mail bandwidth 5% priority 3 qlimit 500 hfsc (realtime 5%)
queue bittor bandwidth 1% priority 2 qlimit 500 hfsc (upperlimit 98%)
queue spamd bandwidth 1% priority 1 qlimit 500 hfsc (upperlimit 1Kb)

 

Разбор правил: шаг за шагом

 #Comcast Upload = 1000Kb/s (queue at 96%)

 Это просто комментарий. Вы никогда не должны использовать полную пропускную способность канала. На comcast хоршим значением является 96%.

 Почему? Вы хотите использовать очереди как средство ограничения канала.
Когда вы отправляете данные и нагружаете канал, маршрутизатор, с которым вы соединяетесь,
решает, какие пакеты идут первыми, хотя именно этого мы и хотим от своего HSFC.
Мы можем не доверять вышестоящему маршрутизатору сортировать ваши пакеты, что происходит в случае, если не используется HSFC на нашей стороне.

 Итак, мы указываем скорость меньше полной полосы пропускания.
«Неужели мы потратим часть полосы впустую?», можете спросить вы. Да, в этом примере мы не используем 5KB/s, но необходимо помнить,
что мы удостоверяемся, что маршрутизаторы провайдера отсылают пакеты в порядке, котором определяем мы, а не они.
Это имеет значение для пакетов ACK и фактически увеличит доступную полосу пропускания на загруженных каналах.

 altq on $ExtIf bandwidth 960Kb hfsc queue { ack, dns, ssh, web, mail, bulk, bittor, spamd }

 Вторая строка — родительская очередь для внешнего интерфейса ($ExtIf), в которой указано, что мы используем «hfsc queue» и список всех восьми дочерних очередей (ack, dns, ssh, web, mail, bulk, bittor, spamd). Также, мы определяем предел полосы пропускания в 96% от полного 1000КБ = 960КБ.

 Следующий набор строк определяет восемь дочерних очередей и также две поддочерних очереди в правиле ssh. Все эти правила используют внешний интерфейс и ограничены полосой пропускания родительской очереди.

 ПОМНИТЕ: не устанавливайте загрузку своей полосы пропускания слишком высоко, иначе очереди в pf будет бесполезны. Обычная практика состоит в том, чтобы установить максимальную полосу пропускания в пределах 9 % полной скорости канала. Установка вашей максимальной скорости в низкие значения более предпочтительно, чем ее увеличение.

 queue ack bandwidth 30% priority 8 qlimit 500 hfsc (realtime 20%)

 Это очередь пакетов ack.
Относительно полной полосы пропускания, заниматься может до 30% канала, установлен самый высокий приоритет 8
и установлено ограничение в 500 слотов.
В реальном времени должно пропускаться 20% данного трафика,
это гарантия для, по крайней мере, 20% пакетов от полной полосы пропускания независимо от того, что хотят другие правила.

 Пакетам ack (acknowledge) установлен самый высокий приоритет. Пакеты Ack посылаются удаленной системе в качестве подтверждения того, что вы получили отправленный ей пакет и готовы принимать следующий. Таким образом мы обеспечим максимальную производительность даже на загруженных линиях. Например, если вы загружаете файл и получили пакет, удаленная система не будет посылать следующий, пока ваша система не ответит подтверждением о получении, пока она не скажет ОК . OK — это как раз пакет ack. Когда вы отправили ack пакет, удаленная система знает, что вы получили отправленный ей пакет, и таким образом это пошлет следующий. С другой стороны, если вы задержите ack пакет, то скорость передачи быстро уменьшится, так как удаленная система прекратит передачу.

 queue dns bandwidth 5% priority 7 qlimit 500 hfsc (realtime 5%)

 Это очередь запросов dns.
С помощью этого правила мы выделяем данному типу трафика целых 5% полной полосы пропускания, приоритет устанавливаем вторым по значимости — 7 и выделяем 500 слотов. Соотношение realtime трафика составляет 5%.

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

 
queue ssh bandwidth 20% priority 6 qlimit 500 hfsc (realtime 20%) {ssh_login, ssh_bulk}
   queue ssh_login bandwidth 50% priority 6 qlimit 500 hfsc
   queue ssh_bulk bandwidth 50% priority 5 qlimit 500 hfsc


 Это набор из родительского и дочерних правил для трафика ssh. Родительская очередь берет 20% от общей полосы пропускания, имеет 6 приоритет, ей назначено 500 слотов. В реальном времени должно пропускаться 20% данного трафика, это гарантия для, по крайней мере, 20% пакетов от полной полосы пропускания независимо от того, что хотят другие правила.

 Два дочерних правила определяют трафик авторизации (ssh_login) и данных, таких как scp/sftp (ssh_bulk). Каждому типу трафика назначено 50% от общих 20% полной полосы пропускания. У обеих дочерних очередей есть способность совместно использовать полосу пропускания друг друга. Приоритеты дочерних очередей ssh независимы от других очередей. Возможно, вы захотите назначить другие приоритеты, поскольку приоритет ssh_login может быть выше чем ssh_bulk.

 Обычно, ключевому слову «queue» соответствует только одно имя, но если определено второе, то очередь будет будет использоваться для пакетов с флагом Type of Service (ToS), имеющих значение low-delay (tos 0x10) и пакетов TCP ACK, не несущих полезной нагрузки в виде данных. Хороший пример можно получить, разобрав работу SSH. Интерактивный SSH трафик маркируется флагом ToS со значением low-delay до тех пор, пока не начнет передаваться трафик SCP или SFTP. PF может использовать эту информацию для интерактивных пакетов и пакетов передачи данных, что может быть полезным при назначении приоритетов.

 Помните: когда вы пишете разрешающие правила для ssh трафика, вы должны соблюсти правильный порядок следования. Для ssh первым правилом должно идти описание трафика передачи данных, а вторым — описание интерактивного трафика. Для примера, «queue (ssh_bulk, ssh_login)» будет правильным порядком. Для получения готового рабочего примера, обратитесь к OpenBSD Pf Firewall «how to» (pf.conf) Guide.

 queue bulk bandwidth 20% priority 5 qlimit 500 hfsc (realtime 20% default)

 Эта очередь, куда пойдет весь трафик, для которого не написаны свои правила очередей. Обратите внимание на директиву «default» после тэга «realtime». Вы должны определить одну и только одну очередь «default».

 queue web bandwidth 5% priority 4 qlimit 500 hfsc (realtime (10%, 2000, 5%) )

 Эта очередь описывает пример использования nonlinear service curve (nlsc или просто sc) в тэге «realtime». Такая очередь может быть назначена публичному web серверу.

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

 В данном примере мы гарантируем 10% от родительской очереди (1000/10 or 100 kbits/sec) в течении 2 секунд от начала передачи данных, после чего снижаем полосу до 5%. Это может бы быть полезным, когда легковесный контент отдается бысро, но ограничена скорость тяжелых загрузок, которые могли бы монополизировать вашу полосу пропускания.

 queue bittor bandwidth 1% priority 2 qlimit 500 hfsc (upperlimit 98%)

 Это правило для торрент-клиента. Все достаточно просто, за исключением того, что у данной очереди нет тэга «realtime», но есть тэг «upperlimit». Это сделано для того, что бы данный трафик мог, при необходимости, полностью освободить выделенную ему полосу пропускания 1%, но когда канал свободен, не занимал более 98% общей полосы пропускания.

 Цель данного правила — показать, как можно управлять p2p трафиком. Если есть запас по полосе пропускания, p2p приложение будет использовать его по полной программе, но как только появится трафик другой очереди, bittor будет возвращена в свои пределы 1%. Например, вы качаете самый свежий дистрибутив OpenBSD и вдруг захотели побробить по Интернетам. В обычной ситуации вам придется биться с p2p клиентом за полосу, что скажется на скорости загрузки страниц, а в данном случае требуема полоса будет освобождена немедленно. При этом очередью bittor будут заниматься qlimit слоты, пока браузер не освободит полосу.

 queue spamd bandwidth 1% priority 1 qlimit 500 hfsc (upperlimit 1Kb)

 Основным отличием данной очереди является то, что она ни при каких обстоятельствах не может занимать больше 1Kb канала.

Применение правил

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

 Здесь мы разберем два правила, использующих очереди. Обратите внимание на имена очередей — ack, bulk, ssh_login и ssh_bulk, которые соответствуют описанным нами выше. Кроме того, важен порядок следования очередей в каждом правиле. Первым, в последовательности очередей «bulk, ack», используется очередь для данных и вторая «ack» для специальных пакетов малой длинны (TOS).

pass out on $ExtIf inet proto tcp from ($ExtIf) to any flags S/SA modulate state queue (ack, bulk)
pass out on $ExtIf inet proto tcp from ($ExtIf) to any port ssh flags S/SA modulate state queue (ssh_login, ssh_bulk)

 Первое правило разрешает исходящий трафик и назначает приоритет ack пакетам. Второе правило разрешает данные по порту 22 (ssh) и расставляет приоритет на интерактивный ssh трафик.

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

pass out on $ExtIf inet proto tcp from ($ExtIf) to any flags S/SA modulate state queue (bulk)

 Также вы можете использовать очереди для данных, передаваемых в рамках stateful сессий. Помните, что вы не можете управлять входящими данными, только исходящими, например, если у вас есть web сервер, то вы можете управлять ответами удаленным клиентам:

pass in on $ExtIf inet proto tcp from any to ($ExtIf) port www flags S/SA modulate state queue (ack, web)

  Хотя есть мнение, что это правило лучше будет выглядеть так (см. комментарии):

pass in on $ExtIf inet proto tcp from any to ($ExtIf) port www flags S/SA modulate state queue (web, ack)

 Для получения дополнительной информации относительно CARP (Common Address Redundancy Protocol) обратитесь к статье
OpenBSD Pf / CARP Firewall Failover.

Проверка работы очередей

 Итак, считаем, что вы все прочитали, поняли и применили на практике. Настала пора проверить работу. Если вы используете OpenBSD версии 4.3 или ниже, то вам необходимо установить из коллекции портов «pftop», если используется OpenBSD 4.4 и выше, то достаточно просто воспользоваться командой «systat queues»:

pfTop: Up Queue 1-9/9, View: queue, Cache: 10000

QUEUE BW SCH PRIO PKTS BYTES DROP_P DROP_B QLEN BORROW SUSPEN P/S B/S
root_rl0 960K hfsc 0 0 0 0 0 0 0 0
ack 595K hfsc 8 950 1345 0 0 0 0 0
dns 52080 hfsc 7 24 734 0 0 0 0 0
ssh 74400 hfsc 6 0 0 0 0 0 0 0
ssh_login 66960 hfsc 6 83 13538 0 0 0 0.2 26
ssh_bulk 7440 hfsc 5 11 3042 0 0 0 0 0
bulk 7440 hfsc 5 406 44540 0 0 0 80 403
web 7440 hfsc 4 99406 564454K 0 0 0 280 34403
mail 7440 hfsc 2 6409 83402K 0 0 0 0 0
bittor 7440 hfsc 2 0 0 0 0 0 0 0
spamd 7440 hfsc 1 24424 1412491 0 0 140 15 923

 То, что вы увидите будет похоже на вышеприведенный пример. Вы должны удостовериться, что трафик распределяется по очередям верно. Например, зайдите по ssh на удаленную машину, после чего поработайте в интерактивном режиме и передайте несколько файлов через scp/sftp (при этом должны увеличиваться счетчики очереди «ssh_bulk»), после чего посмотрите статистику «systat queues».

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



7 комментариев в Использование Hierarchical Fair Service Curve (HFSC) в OpenBSD

  1. ttys:

    http://ru.wikipedia.org/wiki/ALTQ
    это как бы попытка перевода англоязычного wiki на русссий
    описания HFSC были взяты отсюда =)

  2. elf:

    pass out on $ExtIf inet proto tcp from ($ExtIf) to any flags S/SA modulate state queue (ack, bulk) ???

    А должно быть вроде как:
    pass out on $ExtIf inet proto tcp from ($ExtIf) to any flags S/SA modulate state queue (bulk, ack)

  3. Mixa:

    Может быть. Я себе брал примеры с http://www.openbsd.org/faq/pf/queueing.html и https://calomel.org/pf_hfsc.html

  4. elf:

    С https://calomel.org/pf_hfsc.html:

    Here we have two(2) examples of rules you can use queuing on. Notice the queue names we used above like ack, bulk, ssh_login, and ssh_bulk at the end of the rules. Also, notice the order that we have put the two queues in on each rule. The first queue name in «bulk, ack» is for general data and the second «ack» is for special short length packets (TOS).

    pass out on $ExtIf inet proto tcp from ($ExtIf) to any flags S/SA modulate state queue (bulk, ack)
    pass out on $ExtIf inet proto tcp from ($ExtIf) to any port ssh flags S/SA modulate state queue (ssh_bulk, ssh_login)

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

  5. test:

    так если первым задаются данные то следует отсюда что у тебя стоит аск потом веб это явно не то! вот так надо:
    pass in on $ExtIf inet proto tcp from any to ($ExtIf) port www flags S/SA modulate state queue (web, ack)

  6. Mixa:

    Ок! Принимаем к сведению 🙂

  7. test:

    и pass out не надо везде писать пишется просто pass in и всё, это посути и будет исходящий трафик на выходе

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *


*