организация очередей в linux-htb

Я нашел его после прочтения этого ответа суперпользователя , отмечая этот комментарий

Но не для PID (-p), потому что он печатает только конкретный процесс, а для сеанса (-g)

и экспериментального

ps f -g

результата

$ ./script.sh $$
  PID TTY      STAT   TIME COMMAND
14492 pts/24   Ss     0:00 -bash
 9906 pts/24   S+     0:00  \_ bash ./script.sh 14492
 9907 pts/24   R+     0:00      \_ ps f -g14492

1
06.04.2019, 20:39
3 ответа

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

Немного теории :Существует два вида дисциплин организации очередей :классовые и бесклассовые.

Классовые дисциплины (как говорится в ответе sourcejedi )гибкие. Они позволяют вам присоединять к ним дочерние классовые qdisc и могут совместно использовать полосу пропускания с другими классами, когда это возможно.Листовые классы имеют бесклассовый qdisc (elementary/fundamental qdisc ), прикрепленный к ним (, также называемый элементарным qdisc ). Очереди, управляемые этими элементарными qdisc, — это место, где пакеты помещаются в очередь и удаляются из очереди. Пакеты удаляются из очереди и помещаются в очередь из этих классов с помощью алгоритма, соответствующего классу. Примерами классовых qdisc являются :HTB и CBQ.

Бесклассовые qdisc — это фундаментальные или элементарные qdisc, которые являются жесткими в том смысле, что к ним не могут быть прикреплены дочерние qdisc, а также они не могут совместно использовать полосу пропускания. Говоря наивным языком, они предоставлены сами себе. Эти qdisc владеют очередью, из которой они ставят в очередь и удаляют пакеты в соответствии с алгоритмом, соответствующим qdisc. Примеры бесклассового qdisc :pfifo, bfifo, pfifo _fast (по умолчанию, используемые в Linux tc ), tbf, sfq и некоторые другие.

В примере дерева в вопросе каждый из листовых классов htb 1 :1, 1 :2 и 1 :3 имеет прикрепленный к нему элементарный qdisc, который по умолчанию является pfifo (не pfifo _быстро ). Элементарный qdisc, прикрепленный к листу, можно изменить с помощью пользовательской утилиты tcследующим образом:

tc qdisc add dev eth0 parent 1:11 handle 30: pfifo limit 5 
tc qdisc add dev eth0 parent 1:12 handle 40: sfq perturb 10

Более подробную информацию об этом можно найти в руководстве по организации очередей HTB Linux . Поэтому дерево на самом деле выглядит так:

       1: root qdisc (class htb)
     (100)
     / | \ 
    /  |  \
   /   |   \
 1:1  1:2  1:3    parent qdiscs (class htb)
(30)  (10)  (60)
 ||    ||    || -----> pfifo qdiscs (queue length: txqueuelen (default, can be changed by tc utitlity))

Обратите внимание, что параметр txqueuelen является параметром, -специфичным для интерфейса. Это означает, что параметр является свойством интерфейса и может быть изменен с помощью iproute2или ifconfig. По умолчанию его значение равно 1000. Вот пример того, как изменить его на 200 черезiproute2:

ip link set eth0 txqueuelen 200

Когда конечный узел создается (в контексте HTB qdisc ), pfifo qdisc по умолчанию присоединяется к листовому классу. Этот pfifo инициализируется с ограничением очереди txqueuelen интерфейса. Это можно найти в функции htb_change_class()в сч _htb.c ,строка 1395:

/* create leaf qdisc early because it uses kmalloc(GFP_KERNEL)
 * so that can't be used inside of sch_tree_lock
 * -- thanks to Karlis Peisenieks
 */
new_q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
                          classid, NULL);

Длину очереди по умолчанию для очереди pfifo см. в sch _fifo.c , строка 61 :

.
u32 limit = qdisc_dev(sch)->tx_queue_len;

Ядро напрямую взаимодействует с корневым qdisc (, может быть классовым или бесклассовым ), когда оно хочет поставить пакет в очередь или удалить из очереди. Если корневой qdisc является классовым и имеет потомков, то он сначала классифицирует пакет (и решает, какому потомку отправить пакет ). Исходный код ядра, где это делается:sch _htb.c , строка 209:

static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,
                                      int *qerr)

Читая комментарии, можно легко сделать вывод, что эта функция возвращает одно из следующих:

  1. NULL, если пакет нужно отбросить

  2. -1, если пакет должен быть поставлен в очередь в прямую _очередь

  3. листовой узел (который содержит элементарный qdisc, где фактически заканчиваются пакеты )Эта функция проходит через все внутренние узлы (Классы )дерева пока он не вернет конечный узел, где пакет должен быть поставлен в очередь.

При исключении из очереди каждый из классов следует алгоритму, связанному с их qdisc, чтобы решить, из какого из дочерних элементов исключить из очереди, и дочерние элементы делают то же самое, пока пакет не будет удален из очереди из элементарного qdisc, присоединенного к листовому классу. Это также гарантирует, что скорость дочернего класса не больше, чем у его родителя. (Так как родитель будет решать, пройдет пакет или нет ). Я не изучал источник удаления из очереди в htb, поэтому не могу предоставить его источник.

Прямая очередь:Это специальная внутренняя очередь fifo, поддерживаемая qdisc HTB, из которой пакеты удаляются из очереди с аппаратной скоростью. Длина его очереди равна txqueuelen. Пакет попадает в прямую очередь, если HTB не может отнести его к одному из дочерних qdisc, а значение по умолчанию не указано.

Итак, ответы на мои собственные вопросы:

  1. Да,поскольку они являются листовыми узлами, по умолчанию они являются очередями pfifo с длиной очереди txqueuelen интерфейса, которая по умолчанию равна 1000 и может быть изменена.

  2. Дисциплина обслуживания очередей подобна алгоритму вместе с очередью, объединенными в единый пакет! Если вы спросите меня, организация очереди является свойством как типа очереди, так и планировщика пакетов (, здесь планировщик пакетов означает алгоритм, который ставит пакет в очередь и удаляет из очереди ). Например, очередь может иметь тип pfifo или bfifo. Алгоритм, используемый для постановки в очередь и удаления из очереди, одинаков, но длина очереди измеряется в байтах для байта fifo (bfifo ). Пакеты сбрасываются в bfifo, когда достигается лимит байтов. Предел байтов по умолчанию рассчитывается как mtu*txqueuelen. Например, когда пакет ставится в очередь, длина пакета добавляется к текущей длине очереди. Точно так же, когда пакет исключен из очереди, длина пакета вычитается из длины очереди.

  3. Ответ выше.

Некоторые источники, к которым можно обратиться:

  1. Управление сетевым трафиком Linux — обзор реализации (PDF)

  2. Путешествие в центр ядра Linux :Управление трафиком, формирование и качество обслуживания

  3. Демистификация TC -Блог исследований и разработок Criteo

  4. Очередь в сетевом стеке Linux -Журнал Linux

3
27.01.2020, 23:22

Отказ от ответственности:У меня много вопросов, а я не использовал HTB уже лет десять? Так что с уверенностью ответить не могу. Но так как вы пока не получили ни одного ответа, возможно, это все же поможет.


Are there internal queues maintained for each of the parent htb classes (1:1, 1:2 and 1:3)?

Это конечные классы, и каждый из них представлен структурой очереди qdisc, поэтому я предполагаю, что это считается внутренними очередями. Не уверен насчет длины очереди -извините.

Код из сх _htb.c:

struct htb_class_leaf {
    int     deficit[TC_HTB_MAXDEPTH];
    struct Qdisc    *q;
} leaf;

структура Qdisc определена в include/net/sch _generic.h

What exactly is meant by Queueing Discipline (QDisc)?

Это зависит от контекста, но в основном это API ядра, в котором пакеты ставятся в очередь и удаляются из очереди; таким образом, QDisc получает некоторый контроль над порядком (или временем, когда )входящие пакеты должны снова отправляться (или вообще отбрасываться, даже ). Вот как QDisc, такие как HTB, SFQ или PRIO, затем формируют трафик различными способами, например, расставляют приоритеты или накладывают ограничения на пропускную способность.

Комментарий от sch _api.c:

   Generally, queueing discipline ("qdisc") is a black box,
   which is able to enqueue packets and to dequeue them (when
   device is ready to send something) in order and at times
   determined by algorithm hidden in it.

И HTB — лишь один из нескольких таких алгоритмов.

What is a direct_queue?

Не является частью API, но обрабатывается внутри... так что вы можете считать это частью алгоритма HTB.

Если вы намеренно относите пакеты к X:0или если класс по умолчанию не существует, HTB решил поместить их в отдельную очередь, и при исключении из очереди он попытается отправить эти пакеты первыми.

Комментарий от sch _htb.c

 * [...] If we end up with classid MAJOR:0 we enqueue the skb into special
 * internal fifo (direct). These packets then go directly thru. If we still
 * have no valid leaf we try to use MAJOR:default leaf. It still unsuccessful
 * then finish and return direct queue.

... и здесь он сначала удаляет из очереди прямые пакеты .

Обычно это результат неправильной конфигурации (отправки пакетов несуществующему классу ), но разработчики HTB решили, что в этом случае весь трафик должен быть пропущен, а не отброшен весь трафик (слишком разрушительно ).

3
27.01.2020, 23:22

Некоторые быстрые поиски на основе смутных воспоминаний:

HTB является гибким. По умолчанию я думаю, что вы получаете FIFO для каждого листового класса, возможно, он использует конфигурацию по умолчанию для FIFO. Однако вы также можете, например. используйте PFIFO или FQ _CODEL для конечного класса. См., например. «необязательно прикрепите дисциплины очередей к листовым классам» здесь:http://luxik.cdi.cz/~devik/qos/htb/manual/userg.htm

Думаю, вы их увидите, если побежите tc qdisc show.

«Эта «прямая» очередь используется только в том случае, если один из ваших фильтров явно нацелен на «0» classid htb qdisc»https://lists.bufferbloat.net/pipermail/cerowrt-devel/2013-June/006507.html. Прямая очередь не формируется. Судя по всему, длину прямой очереди теперь можно контролировать, хотя я не знаю, как (и поддерживает ли это )tc.https://patchwork.ozlabs.org/patch/225546/

Я бы не сказал, что есть отдельный "планировщик пакетов". Планировщик пакетов представляет собой QDisc (, хотяman tc-tbfописывает себя как «никогда не планирующий трафик»; это означает, что он никогда не -приказывает ему ).

1
27.01.2020, 23:22

Теги

Похожие вопросы