Linux Advanced Routing & Traffic Control HOWTO | ||
---|---|---|
Назад | Глава 14. Специализированные дисциплины управления очередями. | Вперед |
Esteve Camps
Этот текст -- отрывки из моих тезисов Поддержка QoS в Linux, сентябрь 2000 года.
Исходные документы:
Примеры, прилагаемые к дистрибутиву iproute2
White Paper-QoS protocols and architectures и IP QoS Frequently Asked Questions.
Прежде всего, было бы неплохо, если бы вы предварительно ознакомились с RFC, посвященными данной теме (RFC2474, RFC2475, RFC2597 и RFC2598) по адресам: IETF DiffServ working Group и домашняя страничка проекта diffserv.
Dsmark -- это дисциплина организации очереди, которая предлагает возможности, необходимые в "Differentiated Services" (известной также, как DiffServ, или просто -- DS). DiffServ -- фактически одна из двух архитектур QoS (вторая называется "Integrated Services"), которая базируется на значении поля DS в заголовке IP-пакетов.
Одним из первых решений в IP, которое предлагало некоторый уровень QoS, был "Type of Service" (Тип Обслуживания) -- поле TOS в IP-заголовке. Изменяя это поле, можно было выбрать высокую/низкую пропускную способность, минимальную задержку или высокую надежность. Но это решение не обеспечивало достаточной гибкости, которую требовали вновь появляющиеся услуги (например, приложения реального времени, интерактивные приложения и т.п.). С появлением новых требований, появились и новые архитектуры. Одна из них -- DiffServ, которая подменяет первые шесть битов ToS в пакете IPv4 или октет "класс трафика" в пакете IPv6, полем, с названием DS, в котором можно указать до 64 классов трафика.
Differentiated Services (Дифференцированное Обслуживание) ориентирован на группы. Имеется ввиду, что эта технология ничего не знает о потоках, она ориентирована на группы, а применяемые правила зависят от того, к какой группе направляется пакет.
Сеть маршрутизаторов с поддержкой механизмов DiffServ называют "облаком DiffServ" (или "доменом DiffServ"). Классификация, формирование и установка меток (под установкой меток понимается установка значений в поле DS) происходит на входе в "облако". Внутри домена метка определяет -- какой уровень QoS должен применяться к трафику внутренними маршрутизаторами сети.
Самым большим преимуществом модели DiffServ является то, что она действует на границе "облака". После того как данные пересекли границу, внутренним маршрутизаторам можно не заниматься поддержанием информации о статусе QoS и полностью сосредоточиться на своей основной функции -- маршрутизации.
Фактически, внутри своих локальных доменов, вы можете диктовать любую политику обслуживания, но при соединении с другими DS-доменами вы должны следовать Соглашению об Уровне Обслуживания (SLA).
К этому моменту у вас наверняка возникла масса вопросов. Diffsrv -- это много больше, чем я смог сказать. Вы должны понять, что я не в состоянии в 50 строках изложить содержимое трех RFC. :-)
Как уже было определено выше, в случае с 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.
Эта дисциплина выполняет следующие шаги:
Если вставлена инструкция 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
tc class change dev eth0 classid 1:1 dsmark mask 0x3 value 0xb8Это изменение пары (mask,value) в хеш-таблице, пометит пакеты, принадлежащие классу 1:1.
Теперь перейдем к описанию фильтра TC_INDEX. Кроме всего прочего, фильтр TC_INDEX может использоваться и в других конфигурациях, а не только в тех, которые включают DS услуги.
Базовый синтаксис команды, объявляющей фильтр 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. Со своей стороны я обещаю, что дополню этот текст, как только найду время. Все, что я здесь описал -- есть результат длительных экспериментов. Я буду весьма признателен, если вы сообщите мне об обнаруженных ошибках.
Назад | В начало документа | Вперед |
Алгоритм Кларка-Шенкера-Чанга. | К началу раздела | Ingress qdisc. |