• 14.1. bfifo/pfifo
  • 14.1.1. Параметры и порядок использования.
  • 14.2. Алгоритм Кларка-Шенкера-Чанга.
  • 14.3. DSMARK.
  • 14.3.1. Введение.
  • 14.3.2. Что такое Dsmark и с чем его "едят"?
  • 14.3.3. Основные принципы.
  • 14.3.4. Как работать с Dsmark.
  • 14.3.5. Как работает SCH_DSMARK.
  • 14.3.6. Фильтр TC_INDEX.
  • 14.4. Ingress qdisc.
  • 14.4.1. Параметры и порядок использования.
  • 14.5. Random Early Detection (RED)
  • 14.6. Generic Random Early Detection.
  • 14.7. Эмуляция VC/ATM.
  • 14.8. Weighted Round Robin (WRR).
  • Глава 14. Специализированные дисциплины управления очередями.

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

    14.1. bfifo/pfifo

    Эти бесклассовые дисциплины еще более просты, чем pfifo_fast — они не имеют внутренних полос, все виды трафика в них равноправны. Единственное их преимущество — возможность получения некоторых статистик. Таким образом, если вы не собираетесь ограничивать трафик или раскидывать его по приоритетам, то использование этой дисциплины позволит вам получить дополнительную информацию, которая поможет выявить узкие места на интерфейсе.

    Длина pfifo измеряется в пакетах, bfifo — в байтах.

    14.1.1. Параметры и порядок использования.

    limit

    Задает длину очереди. Для pfifo измеряется в пакетах, для bfifo — в байтах. По-умолчанию имеет значение: для pfifo — txqueuelen интерфейса (см. раздел pfifo_fast), в пакетах, и txqueuelen * mtu байт — для bfifo.

    14.2. Алгоритм Кларка-Шенкера-Чанга.

    Этот алгоритм настолько "заумный", что даже Алексей (главный автор CBQ) утверждает — будто бы не до конца понял его суть. С его слов:

    David D. Clark, Scott Shenker и Lixia Zhang. Поддержка Приложений Реального Времени в Пакетных Сетях c Интеграцией Сервисов: Архитектура и Механизм.

    Насколько я понял, основная идея заключается в создании WFQ-потоков для каждого из сервисов с гарантированным качеством обслуживания и привязка оставшейся пропускной способности к фиктивному потоку flow-0 . В поток flow-0 отправляется весь предиктивный трафик и трафик, который обслуживается по принципу "лучшее из оставшегося" (best effort). Планировщик потока в первую очередь пропускает предиктивный трафик, а оставшаяся пропускная способность отдается трафику "best effort".

    Примечательно, что в CSZ-потоках (Clark-Shenker-Zhang) НЕ производится наложения ограничений пропускной способности. Предполагается, что поток уже прошел входной контроль QoS сети и не нуждается в дополнительном формировании. Любая попытка что-то улучшить или ограничить, на промежуточных переходах, может привести к нежелательным задержкам и увеличению нестабильности.

    На сегодняшний день CSZ – единственный планировщик, который может дать настоящую гарантию качества обслуживания. Другие схемы (включая CBQ) не гарантируют величину задержки.

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

    14.3. DSMARK.

    Esteve Camps

    <marvin@grn.es>

    Этот текст — отрывки из моих тезисов Поддержка QoS в Linux, сентябрь 2000 года.

    Исходные документы:

    Draft-almesberger-wajhak-diffserv-linux-01.txt

    • Примеры, прилагаемые к дистрибутиву iproute2

    White Paper-QoS protocols and architectures и IP QoS Frequently Asked Questions.

    Автор главы: Esteve Camps <esteve@hades.udg.es>.

    14.3.1. Введение.

    Прежде всего, было бы неплохо, если бы вы предварительно ознакомились с RFC, посвященными данной теме (RFC2474, RFC2475, RFC2597 и RFC2598) по адресам: IETF DiffServ working Group и домашняя страничка проекта diffserv.

    14.3.2. Что такое Dsmark и с чем его "едят"?

    Dsmark -— это дисциплина организации очереди, которая предлагает возможности, необходимые в "Differentiated Services" (известной также, как DiffServ, или просто — DS). DiffServ — фактически одна из двух архитектур QoS (вторая называется "Integrated Services"), которая базируется на значении поля DS в заголовке IP-пакетов.

    Одним из первых решений в IP, которое предлагало некоторый уровень QoS, был "Type of Service" (Тип Обслуживания) — поле TOS в IP-заголовке. Изменяя это поле, можно было выбрать высокую/низкую пропускную способность, минимальную задержку или высокую надежность. Но это решение не обеспечивало достаточной гибкости, которую требовали вновь появляющиеся услуги (например, приложения реального времени, интерактивные приложения и т.п.). С появлением новых требований, появились и новые архитектуры. Одна из них — DiffServ, которая подменяет первые шесть битов ToS в пакете IPv4 или октет "класс трафика" в пакете IPv6, полем, с названием DS, в котором можно указать до 64 классов трафика.

    14.3.3. Основные принципы.

    Differentiated Services (Дифференцированное Обслуживание) ориентирован на группы. Имеется ввиду, что эта технология ничего не знает о потоках, она ориентирована на группы, а применяемые правила зависят от того, к какой группе направляется пакет.

    Сеть маршрутизаторов с поддержкой механизмов DiffServ называют "облаком DiffServ" (или "доменом DiffServ"). Классификация, формирование и установка меток (под установкой меток понимается установка значений в поле DS) происходит на входе в "облако". Внутри домена метка определяет — какой уровень QoS должен применяться к трафику внутренними маршрутизаторами сети.

    Самым большим преимуществом модели DiffServ является то, что она действует на границе "облака". После того как данные пересекли границу, внутренним маршрутизаторам можно не заниматься поддержанием информации о статусе QoS и полностью сосредоточиться на своей основной функции — маршрутизации.

    Фактически, внутри своих локальных доменов, вы можете диктовать любую политику обслуживания, но при соединении с другими DS-доменами вы должны следовать Соглашению об Уровне Обслуживания (SLA).

    К этому моменту у вас наверняка возникла масса вопросов. Diffsrv — это много больше, чем я смог сказать. Вы должны понять, что я не в состоянии в 50 строках изложить содержимое трех RFC. :-)

    14.3.4. Как работать с Dsmark.

    Как уже было определено выше, в случае с DiffServ, пограничные и внутренние узлы различаются между собой. Это два важных пункта на пути трафика. Оба типа узлов выполняют классификацию трафика. Результат классификации может использоваться для различной DS-обработки, прежде чем пакет уйдет в сеть. Код diffserv представляет пакет в виде структуры sk_buff, в которой имеется поле skb->tc_index. В данном поле сохраняется результат начальной классификации, который может использоваться для различной интерпретации DS на пограничных и внутренних маршрутизаторах.

    Значение skb->tc_index изначально устанавливается дисциплиной DSMARK qdisc для каждого входящего пакета, в соответствии с полем DS в IP-заголовке. Кроме того, классификатор cls_tcindex считывает, целиком или частично, значение skb->tcindex и использует его для выбора нужного класса.

    Для начала рассмотрим команду DSMARK qdisc и ее параметры:

    … dsmark indices INDICES [ default_index DEFAULT_INDEX ] [ set_tc_index ]

    Каково назначение этих параметров?

    • indices: размер таблицы пар маска-значение. Максимальное значение 2^n, где n >= 0.

    • Default_index: индекс в таблице, принимаемый по-умолчанию, если классификатор не находит ни одного совпадения.

    • Set_tc_index: инструкция, которая считывает значение поля DS и записывает его в skb->tc_index.

    14.3.5. Как работает SCH_DSMARK.

    Эта дисциплина выполняет следующие шаги:

    • Если вставлена инструкция set_tc_index, то считывается поле DS и сохраняется в skb->tc_index.

    • Вызывается классификатор. Он возвращает идентификатор класса, который будет сохранен в skb->tc_index. Если такой класс не найден, то используется класс по-умолчанию из параметра default_index. Если ни set_tc_index, ни default_index не объявлены, то результат может оказаться непредсказуемым.

    • После этого управление передается внутренней qdisc, где вы можете повторно использовать результаты фильтрации. Идентификатор класса, возвращаемый внутренней qdisc, запоминается в skb->tc_index. Это значение будет использоваться в качестве индекса таблицы маска-значение. Конечный результат, который будет связан с пакетом, получается из выражения:

    New_Ds_field = (Old_DS_field & mask) | value

    • Таким образом, конечный результат получается в результате объединения по "И" ds_field и маски, и затем объединения по "ИЛИ" с параметром value. Следующая диаграмма иллюстрирует этот процесс: 

                             skb->ihp->tos

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >

         |                                                       |     ^

         | -- Если объявлена инструкция set_tc_index,            |     |  <-----Значение поля

         |    то значение DS переписывается в skb->tc_index      |     |O       DS может измениться

         |                                                      A|     |R

       +-|-+      +------+    +---+-+    внутренняя +-+     +---N|-----|----+

       | | |      | tc   |--->|   | |-->  . . .  -->| |     |   D|     |    |

       | | |----->|index |--->|   | |     Qdisc     | |---->|    v     |    |

       | | |      |filter|--->| | | +---------------+ |   ---->(mask,value) |

    -->| O |      +------+    +-|-+--------------^----+  /  |  (.  ,  .)    |

       | | |          ^         |                |       |  |  (.  ,  .)    |

       | | +----------|---------|----------------|-------|--+  (.  ,  .)    |

       | | sch_dsmark |         |                |       |                  |

       +-|------------|---------|----------------|-------|------------------+

         |            |         | <- tc_index -> |       |

         |            |(read)   |    может       |       |  <--------------Индекс в таблице

         |            |         |    измениться  |       |                    (mask,value)

         v            |         v                v       |                              

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->

                             skb->tc_index           

     Как установить метку? Просто измените mask и value класса. См. следующий код:

    tc class change dev eth0 classid 1:1 dsmark mask 0x3 value 0xb8

    Это изменение пары (mask,value) в хеш-таблице, пометит пакеты, принадлежащие классу 1:1.

    Теперь перейдем к описанию фильтра TC_INDEX. Кроме всего прочего, фильтр TC_INDEX может использоваться и в других конфигурациях, а не только в тех, которые включают DS услуги.

    14.3.6. Фильтр TC_INDEX.

    Базовый синтаксис команды, объявляющей фильтр TC_INDEX:

    … tcindex [ hash SIZE ] [ mask MASK ] [ shift SHIFT ]

              [ pass_on | fall_through ]

              [ classid CLASSID ] [ police POLICE_SPEC ]

    Ниже приводится пример, который описывает работу TC_INDEX (обратите внимание на места, выделенные жирным шрифтом:

    tc qdisc add dev eth0 handle 1:0 root dsmark indices 64 set_tc_index

    tc filter add dev eth0 parent 1:0 protocol ip prio 1 tcindex mask 0xfc shift 2

    tc qdisc add dev eth0 parent 1:0 handle 2:0 cbq bandwidth 10Mbit cell 8 avpkt 1000 mpu 64

    # EF traffic class

    tc class add dev eth0 parent 2:0 classid 2:1 cbq bandwidth 10Mbit rate 1500Kbit avpkt 1000 prio 1 bounded isolated allot 1514 weight 1 maxburst 10

    # Packet fifo qdisc for EF traffic

    tc qdisc add dev eth0 parent 2:1 pfifo limit 5

    tc filter add dev eth0 parent 2:0 protocol ip prio 1 handle 0x2e tcindex classid 2:1 pass_on

    (Это неполный код, я просто привел часть примера EFCBQ, включенного в состав дистрибутива iproute2).


    Будем исходить из предположения, что мы получаем пакет, помеченный как EF. Если вы прочитаете RFC2598, то увидите, что рекомендуемое значение DSCP для EF трафика — 101110. Это означает, что в поле DS будет записано 10111000 (не забывайте, что младшие биты в поле TOS не используются в DS), или 0xb8, в шестнадцатиричном представлении. 

                  TC INDEX

                  FILTER

       +---+      +-------+    +---+-+    +------+                +-+    +-------+

       |   |      |       |    |   | |    |FILTER|  +-+    +-+    | |    |       |

       |   |----->| MASK  | -> |   | | -> |HANDLE|->| |    | | -> | | -> |       |

       |   |  .   | =0xfc |    |   | |    |0x2E  |  | +----+ |    | |    |       |

       |   |  .   |       |    |   | |    +------+  +--------+    | |    |       |

       |   |  .   |       |    |   | |                            | |    |       |

    -->|   |  .   | SHIFT |    |   | |                            | |    |       |-->

       |   |  .   | =2    |    |   | +----------------------------+ |    |       |

       |   |      |       |    |   |       CBQ 2:0                  |    |       |

       |   |      +-------+    +---+--------------------------------+    |       |

       |   |                                                             |       |

       |   +-------------------------------------------------------------+       |

       |                          DSMARK 1:0                                     |

       +-------------------------------------------------------------------------+
     

    Полученный пакет имеет значение 0xb8 в поле DS. Дисциплина с идентификатором 1:0 считывает это значение и помещает его в skb->tc_index. На следующем шаге (вторая строка в примере), описанный фильтр выполняет следующие действия:

    Value1 = skb->tc_index & MASK

    Key = Value1 >> SHIFT

    В нашем примере MASK=0xFC и SHIFT=2.

    Value1 = 10111000 & 11111100 = 10111000

    Key = 10111000 >> 2 = 00101110 -> 0x2E (в шестнадцатиричном виде)

    Возвращаемое значение будет соответствовать фильтру внутренней qdisc (в примере, идентификатор 2:0). Если фильтр с заданным идентификатором найден, то условия фильтра будут проверены (в случае, если фильтр включает в себя эти условия) и будет возвращен classid (в нашем примере classid 2:1), который далее будет записан в skb->tc_index. Если фильтр не будет найден, то результат будет зависеть от объявления флага fall_through. Если объявление fall_through присутствует, то его значение будет воспринято как classid. В противном случае продолжится просмотр остальных фильтров. Будьте предельно внимательны, при использовании флага fall_through — его использование рекомендуется только в том случае, когда значение skb->tc_index и идентификаторы классов ссвязаны простыми (в смысле несложными) отношениями.

    И последние два параметра, которые мы опишем, это hash и pass_on. Первый из них определяет размер хеш-таблицы. Pass_on — означает, что если не будет найден classid, равный результату этого фильтра, то необходимо попробовать применить следующий фильтр. Действие по-умолчанию — fall_through (см. следующую таблицу).

    В заключение посмотрим — какие значения параметров TCINDEX допустимы:

    TC Name Value Default
    Hash 1...0x10000 Зависит от реализации
    Mask 0...0xffff 0xffff
    Shift 0...15 0
    Fall through / Pass_on Flag Fall_through
    Classid Major:minor None
    Police  ..... None       

    Это очень мощный тип фильтров. Кроме того, он может использоваться не только в конфигурации DiffServ, но и как любой другой тип фильтров.

    Я настоятельно рекомендую вам внимательно просмотреть все примеры DiffServ, включаемые в дистрибутив iproute2. Со своей стороны я обещаю, что дополню этот текст, как только найду время. Все, что я здесь описал — есть результат длительных экспериментов. Я буду весьма признателен, если вы сообщите мне об обнаруженных ошибках.

    14.4. Ingress qdisc.

    До сих пор, все дисциплины, которые обсуждались, были исходящими (egress) дисциплинами. Однако, каждый из интерфейсов может иметь и входящие (ingress) дисциплины. Они не применяются к исходящему трафику, но они позволяют устанавливать tc-фильтры для входящих пакетов, вне зависимости от того, предназначены ли они для данного хоста или должны быть перенаправлены дальше.

    Поскольку tc-фильтры имеют полную реализацию Token Bucket Filter, то они так же могут ограничивать входящий трафик на основе "функций оценки" (estimators). Это позволяет выстраивать эффективную политику обслуживания входящего трафика, до того как он попадет "в руки" стека протоколов IP.

    14.4.1. Параметры и порядок использования.

    Входные дисциплины, сами по себе не требуют каких-либо параметров. Пример создания входной дисциплины:

    # tc qdisc add dev eth0 ingress

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

    Примеры использования входящей дисциплины вы найдете в главе Решебник.

    14.5. Random Early Detection (RED)

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

    Нередко на маршрутизаторах в Интернет возникает так называемая проблема tail drops – отсечения конца очереди. Когда очередь полна, ни один вновь поступивший пакет туда уже не помещается, а потому отбрасывается. Такое управление очередью приводит к повторной синхронизации параметров соединения. После синхронизации TCP сразу посылает столько пакетов, сколько допускает размер окна подтверждения. Подобный всплеск нагрузки опять приводит к отсечению конца очереди, что опять порождает необходимость повторной синхронизации… Такое хождение по кругу может продолжаться довольно долго.

    Чтобы избежать возникновения заторов, на маршрутизаторах зачастую организуются очереди большого размера. К сожалению, не смотря на то, что увеличение размеров очереди благоприятно сказывается на пропускной способности, большие очереди могут приводить к увеличению времени задержки, что становится причиной взрывоподобного поведения TCP-соединений.

    Проблема отсечения хвоста очереди с каждым днем становится все более неприятной. Для предотвращения перегрузок, ядро Linux предоставляет в наше распоряжение механизм RED, сокращенно от Random Early Detect (Случайное Раннее Обнаружение), которое иногда называется как Random Early Drop (Случайное Раннее Отсечение), последнее определение более точно описывает принцип работы.

    RED — это не панацея от всех бед, но позволяет более "справедливо" разделить канал между TCP-соединениями.

    Он позволяет контролировать нагрузку с помощью выборочного случайного уничтожения некоторых пакетов до того, как очередь будет заполнена полностью, что заставляет протоколы, подобные TCP, снижать скорость передачи и предотвращает повторную синхронизацию. Кроме того, выборочная "потеря" пакетов помогает TCP быстрее найти подходящую скорость передачи данных, а так же удерживать размер очереди и время задержки на разумном уровне. Вероятность "потери" пакета конкретного соединения прямо пропорциональна пропускной способности, используемой этим соединением, а не числу пакетов, т.е. большие пакеты уничтожаются чаще маленьких, что дает достаточно справедливое распределение полосы пропускания.

    RED хорошо подходит для обслуживания очередей на магистральных линиях, где отслеживание сессий (с целью справедливого распределения канала) является непозволительной роскошью.

    При работе с RED вы должны будете определиться со значениями трех параметров: Минимум (min), Максимум (max) и Превышение (burst). Минимум — это минимальный размер очереди в байтах, выше которого начнется выборочная потеря пакетов. Максимум – это "мягкий" максимум, алгоритм будет пытаться удержать размер очереди ниже этого предела. Превышение — максимальное число пакетов, которые могут быть приняты в очередь сверх установленного максимального предела.

    Минимальный размер очереди рассчитывается, исходя из максимально допустимого времени задержки в очереди и пропускной способности канала. Например, на моем 64Кбит/сек (8 Кбайт/сек) соединении я хочу получить максимальное время задержки 200 мсек, тогда 8 * 0.2 = 1.6 Кбайт (т.е. примерно 1600 байт). Если установить минимальный предел слишком маленьким, это приведет к снижению пропускной способности, слишком большим – к увеличению времени задержки. Уменьшение размера очереди не может служить заменой уменьшению размера MTU, которое используется для уменьшения времени отклика на медленных линиях связи.

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

    Предел превышения отвечает за поведение RED на пиковых нагрузках. Размер превышения должен устанавливаться больше, чем min/avpkt. Экспериментальным путем я пришел к выражению, устанавливающему размер превышения, (min+min+max)/(3*avpkt), которое дает неплохие результаты.

    Кроме того, вам необходимо будет определиться с предельным размером очереди (limit) и средним размером пакета (avpkt). По достижении очередью предельного размера, RED переходит к алгоритму "отсечения конца". Обычно я устанавливаю предельный размер очереди в 8 раз больше максимального. Значение 1000, для avpkt (средний размер пакета), дает неплохие результаты на высокоскоростных линиях, при размере MTU = 1500.

    Техническое описание RED (авторы: Sally Floyd и Van Jacobson) вы найдете в документе the paper on RED queueing.

    14.6. Generic Random Early Detection.

    Этот алгоритм известен не так широко. Он напоминает RED с несколькими внутренними очередями, распределение пакетов по очередям производится на базе поля tcindex Diffserv.

    Каждая из виртуальных очередей может иметь собственные параметры конфигурации.

    FIXME: убедительная просьба к Джамалу (Jamal) и Вернеру (Werner) дополнить этот раздел

    14.7. Эмуляция VC/ATM.

    Возможность строить Виртуальные Соединения через сокеты TCP/IP, появилась целиком и полностью благодаря усилиям Вернера Альмсбергера (Werner Almesberger). Виртуальные соединения — это концепция, пришедшая из теории построения сетей ATM.

    Дополнительную информацию по этой теме вы найдете по адресу: http://linux-atm.sourceforge.net/.

    14.8. Weighted Round Robin (WRR).

    Эта дисциплина организации очередей не включена в состав ядра Linux, однако вы можете скачать все необходимое по адресу: http://wipl-wrr.dkik.dk/wrr/. Она была протестирована только на ядрах серии 2.2, но возможно будет работать и на ядрах серий 2.4/2.5

    WRR qdisc распределяет пропускную способность по классам, используя схему взвешенного циклического обхода. Т.е., подобно CBQ qdisc, она содержит классы, которые могут включать в себя любые другие дисциплины. Все классы получают ширину канала, пропорциональную присвоенным им весам. Весовые коэффициенты могут быть установлены как вручную, с помощью утилиты tc, так и автоматически, в этом случае величина весового коэффициента устанавливается обратно пропорциональной объему передаваемых через класс данных.

    Дисциплина имеет внутренний классификатор, который распределяет пакеты, идущие на/из разные узлы сети, по разным классам. Определение отправителя/получателя может производиться на основе MAC или IP адреса. Однако, MAC адреса могут использоваться только в ethernet сетях. Привязка хостов к классам происходит автоматически, при появлении первых пакетов, прошедших по соединению.

    Она неплохо зарекомендовала себя при обслуживании небольших локальных сетей, например в студенческих общежитиях, когда между несколькими индивидами разделяется единственное соединение с Интернет. Центральной частью дистрибутива WRR является набор сценариев, выполняющих настройку алгоритма для таких сетей.







     

    Главная | В избранное | Наш E-MAIL | Добавить материал | Нашёл ошибку | Наверх