qosd: добавлены атрибуты узлов

Мне показалось, будет удобно использовать вложенную структуру в качестве
аргумента конструктора.
This commit is contained in:
Сергей Маринкевич
2025-09-03 20:12:47 +07:00
parent 6a82699c5c
commit 43b44d7ee5
7 changed files with 144 additions and 11 deletions
+16 -1
View File
@@ -1,5 +1,6 @@
#pragma once #pragma once
#include <cstdint>
#include "nodes/LeafNode.h" #include "nodes/LeafNode.h"
#include "mixins/FabricMixin.h" #include "mixins/FabricMixin.h"
#include "Logger.h" #include "Logger.h"
@@ -8,14 +9,28 @@
class BFIFONode : public LeafNode, class BFIFONode : public LeafNode,
public FabricMixin<BFIFONode> { public FabricMixin<BFIFONode> {
public: public:
struct Config {
/// Размер очереди в байтах.
std::uint64_t limit = 0;
};
~BFIFONode() { ~BFIFONode() {
Logger::get("ConDes").dbg(std::string("--- BFIFO destructor called for: ") + name_); Logger::get("ConDes").dbg(std::string("--- BFIFO destructor called for: ") + name_);
} }
const Config& config() const { return config_; }
private: private:
friend class FabricMixin<BFIFONode>; friend class FabricMixin<BFIFONode>;
BFIFONode(std::string name) : LeafNode(std::move(name), "BFIFO") { BFIFONode(std::string&& name) : LeafNode(std::move(name), "BFIFO") {
Logger::get("ConDes").dbg(std::string("--- BFIFO constructor called for: ") + name_); Logger::get("ConDes").dbg(std::string("--- BFIFO constructor called for: ") + name_);
} }
BFIFONode(std::string&& name, Config&& config) : LeafNode(std::move(name), "BFIFO"),
config_(std::move(config)) {
Logger::get("ConDes").dbg(std::string("--- BFIFO constructor called for: ") + name_);
}
Config config_{};
}; };
+32 -2
View File
@@ -1,5 +1,7 @@
#pragma once #pragma once
#include <cstdint>
#include <string>
#include "nodes/ComplexNode.h" #include "nodes/ComplexNode.h"
#include "mixins/FabricMixin.h" #include "mixins/FabricMixin.h"
#include "Logger.h" #include "Logger.h"
@@ -8,16 +10,44 @@
class HTBNode : public ComplexNode, class HTBNode : public ComplexNode,
public FabricMixin<HTBNode> { public FabricMixin<HTBNode> {
public: public:
struct Config {
std::uint64_t cir = 0; ///< Разрешённая полоса, CIR, бит/с.
std::uint64_t cburst = 0; ///< Токены для CIR, байты.
std::uint64_t pir = 0; ///< Допустимая полоса, PIR, бит/с.
std::uint64_t pburst = 0; ///< Токены для PIR, байты.
std::uint32_t prio = 0; ///< Приоритет класса.
std::uint32_t quantum = 0; ///< Квант DRR, байты.
/// \brief Поправка размера пакета, байты.
///
/// \note Вообще, этот параметр исторически взят с Linux/TC HTB.
/// И в таком контексте: речь **не** про STAB, а именно про
/// параметр класса HTB. Он, в отличие от STAB, не влияет на сам
/// размер пакета, а используется только для поправки шейпера
/// конкретно этого класса. Впрочем, в BC2 есть такая же местная
/// поправка для шейперов, см. FS 31.5.2.3 Packet Length Offset.
std::int32_t overhead = 0;
};
~HTBNode() { ~HTBNode() {
Logger::get("ConDes").dbg(std::string("--- HTB destructor called for: ") + name_); Logger::get("ConDes").dbg(std::string("--- HTB destructor called for: ") + name_);
} }
const Config& config() const { return config_; }
private: private:
friend class FabricMixin<HTBNode>; friend class FabricMixin<HTBNode>;
HTBNode(std::string name) HTBNode(std::string&& name) : ComplexNode(std::move(name)) {
: ComplexNode(std::move(name)) {
kind_ = "HTB"; kind_ = "HTB";
Logger::get("ConDes").dbg(std::string("--- HTB constructor called for: ") + name_); Logger::get("ConDes").dbg(std::string("--- HTB constructor called for: ") + name_);
} }
HTBNode(std::string&& name, Config&& config) : ComplexNode(std::move(name)),
config_(std::move(config)) {
kind_ = "HTB";
Logger::get("ConDes").dbg(std::string("--- HTB constructor called for: ") + name_);
}
Config config_{};
}; };
+16 -1
View File
@@ -1,5 +1,6 @@
#pragma once #pragma once
#include <cstdint>
#include "nodes/LeafNode.h" #include "nodes/LeafNode.h"
#include "mixins/FabricMixin.h" #include "mixins/FabricMixin.h"
#include "Logger.h" #include "Logger.h"
@@ -8,14 +9,28 @@
class PFIFONode : public LeafNode, class PFIFONode : public LeafNode,
public FabricMixin<PFIFONode> { public FabricMixin<PFIFONode> {
public: public:
struct Config {
/// \brief Кол-во пакетов.
std::uint32_t limit;
};
~PFIFONode() { ~PFIFONode() {
Logger::get("ConDes").dbg(std::string("--- PFIFO destructor called for: ") + name_); Logger::get("ConDes").dbg(std::string("--- PFIFO destructor called for: ") + name_);
} }
const Config& config() const { return config_; }
private: private:
friend class FabricMixin<PFIFONode>; friend class FabricMixin<PFIFONode>;
PFIFONode(std::string name) : LeafNode(std::move(name), "PFIFO") { PFIFONode(std::string&& name) : LeafNode(std::move(name), "PFIFO") {
Logger::get("ConDes").dbg(std::string("--- PFIFO constructor called for: ") + name_); Logger::get("ConDes").dbg(std::string("--- PFIFO constructor called for: ") + name_);
} }
PFIFONode(std::string&& name, Config&& config) : LeafNode(std::move(name), "PFIFO"),
config_(std::move(config)) {
Logger::get("ConDes").dbg(std::string("--- PFIFO constructor called for: ") + name_);
}
Config config_{};
}; };
+29 -1
View File
@@ -1,21 +1,49 @@
#pragma once #pragma once
#include <cstdint>
#include "nodes/LeafNode.h" #include "nodes/LeafNode.h"
#include "mixins/FabricMixin.h" #include "mixins/FabricMixin.h"
#include "Logger.h" #include "Logger.h"
/// \brief Узел дисциплины RED. Лист; не допускает дочерних элементов. /// \brief Узел дисциплины RED. Лист; не допускает дочерних элементов.
///
/// \note Может быть подключен к:
/// + WRED для настройки VQ;
/// + SFQ для настройки per-flow RED.
class REDNode : public LeafNode, class REDNode : public LeafNode,
public FabricMixin<REDNode> { public FabricMixin<REDNode> {
public: public:
struct Config {
std::uint64_t limit = 0; ///< Размер буфера, байты (обязателен).
std::uint64_t min = 0; ///< Нижняя граница для разметки, байты.
std::uint64_t max = 0; ///< Верхняя граница для разметки, байты.
std::uint32_t avpkt = 0; ///< Средний размер пакета, байты (обязателен).
std::uint64_t burst = 0; ///< Всплеск, байты.
double probability = 0.0; ///< Максимальная вероятность, 0..1.
std::uint64_t bandwidth = 0; ///< Скорость интерфейса, бит/с.
bool ecn = false; ///< Включить ECN-разметку вместо дропа.
bool harddrop = false; ///< Жёсткий дроп при превышении max.
bool nodrop = false; ///< Не дропать non-ECN-пакеты.
};
~REDNode() { ~REDNode() {
Logger::get("ConDes").dbg(std::string("--- RED destructor called for: ") + name_); Logger::get("ConDes").dbg(std::string("--- RED destructor called for: ") + name_);
} }
const Config& config() const { return config_; }
private: private:
friend class FabricMixin<REDNode>; friend class FabricMixin<REDNode>;
REDNode(std::string name) : LeafNode(std::move(name), "RED") { REDNode(std::string&& name)
: LeafNode(std::move(name), "RED") {
Logger::get("ConDes").dbg(std::string("--- RED constructor called for: ") + name_); Logger::get("ConDes").dbg(std::string("--- RED constructor called for: ") + name_);
} }
REDNode(std::string&& name, Config&& config)
: LeafNode(std::move(name), "RED"), config_(std::move(config)) {
Logger::get("ConDes").dbg(std::string("--- RED constructor called for: ") + name_);
}
Config config_{};
}; };
+23 -1
View File
@@ -1,5 +1,6 @@
#pragma once #pragma once
#include <cstdint>
#include "nodes/BaseNode.h" #include "nodes/BaseNode.h"
#include "mixins/LazyLinkMixin.h" #include "mixins/LazyLinkMixin.h"
#include "mixins/FabricMixin.h" #include "mixins/FabricMixin.h"
@@ -12,15 +13,36 @@ class SFQNode : public BaseNode,
virtual public LazyLinkMixin<TypedOneToOneLink<INode, REDNode>>, virtual public LazyLinkMixin<TypedOneToOneLink<INode, REDNode>>,
public FabricMixin<SFQNode> { public FabricMixin<SFQNode> {
public: public:
/// \note Параметры RED per-flow задаются через дочерний REDNode.
struct Config {
std::uint32_t limit = 0; ///< Суммарный лимит по всем потокам, пакеты
std::uint32_t depth = 0; ///< Лимит на один поток, пакеты
std::uint32_t divisor = 1024; ///< Размер хэш-таблицы (степень двойки)
std::uint32_t perturb = 0; ///< Период пертурбации, секунды
std::uint32_t flows = 0; ///< Число потоков
std::uint32_t quantum = 0; ///< Порция RR, байты
bool headdrop = false; ///< Отбрасывать из головы очереди
};
~SFQNode() { ~SFQNode() {
Logger::get("ConDes").dbg(std::string("--- SFQ destructor called for: ") + name_); Logger::get("ConDes").dbg(std::string("--- SFQ destructor called for: ") + name_);
} }
const Config& config() const { return config_; }
private: private:
friend class FabricMixin<SFQNode>; friend class FabricMixin<SFQNode>;
SFQNode(std::string name) : BaseNode(std::move(name)) { SFQNode(std::string&& name) : BaseNode(std::move(name)) {
kind_ = "SFQ"; kind_ = "SFQ";
Logger::get("ConDes").dbg(std::string("--- SFQ constructor called for: ") + name_); Logger::get("ConDes").dbg(std::string("--- SFQ constructor called for: ") + name_);
} }
SFQNode(std::string&& name, Config&& config)
: BaseNode(std::move(name)), config_(std::move(config)) {
kind_ = "SFQ";
Logger::get("ConDes").dbg(std::string("--- SFQ constructor called for: ") + name_);
}
Config config_{};
}; };
+20 -1
View File
@@ -1,5 +1,7 @@
#pragma once #pragma once
#include <cstdint>
#include <string>
#include "nodes/BaseNode.h" #include "nodes/BaseNode.h"
#include "mixins/LazyLinkMixin.h" #include "mixins/LazyLinkMixin.h"
#include "mixins/FabricMixin.h" #include "mixins/FabricMixin.h"
@@ -11,15 +13,32 @@ class WREDNode : public BaseNode,
virtual public LazyLinkMixin<TypedOneToManyLink<INode, REDNode>>, virtual public LazyLinkMixin<TypedOneToManyLink<INode, REDNode>>,
public FabricMixin<WREDNode> { public FabricMixin<WREDNode> {
public: public:
struct Config {
bool grio = false; ///< Наследование буферов (GRIO)
std::uint64_t limit = 0; ///< Глобальный лимит буфера, байты (необязателен)
bool ecn = false; ///< Включить ECN на дисциплине
bool harddrop = false; ///< Жёсткий дроп при превышении max
};
~WREDNode() { ~WREDNode() {
Logger::get("ConDes").dbg(std::string("--- WRED destructor called for: ") + name_); Logger::get("ConDes").dbg(std::string("--- WRED destructor called for: ") + name_);
} }
const Config& config() const { return config_; }
private: private:
friend class FabricMixin<WREDNode>; friend class FabricMixin<WREDNode>;
WREDNode(std::string name) : BaseNode(std::move(name)) { WREDNode(std::string&& name) : BaseNode(std::move(name)) {
kind_ = "WRED"; kind_ = "WRED";
Logger::get("ConDes").dbg(std::string("--- WRED constructor called for: ") + name_); Logger::get("ConDes").dbg(std::string("--- WRED constructor called for: ") + name_);
} }
WREDNode(std::string&& name, Config&& config)
: BaseNode(std::move(name)), config_(std::move(config)) {
kind_ = "WRED";
Logger::get("ConDes").dbg(std::string("--- WRED constructor called for: ") + name_);
}
Config config_{};
}; };
+8 -4
View File
@@ -13,10 +13,10 @@
Из дисциплины: Из дисциплины:
+ `default` — Минорная часть ID класса по умолчанию. Dunno, надо ли нам такое вообще. Я об этом не думал. Сейчас у нас всё на фильтры `u32` завязано. + `default` — Минорная часть ID класса по умолчанию. Dunno, надо ли нам такое вообще. Я об этом не думал. Сейчас у нас всё на фильтры `u32` завязано.
+ `r2q` — Кванты DRR (computed as rate in Bps/r2q). КМК, нам это не надо, мы этим никогда не пользовались. Единственное: мы раньше не пользовались DRR, а сейчас я хочу на этом построить Basic QoS. + `r2q` — Кванты DRR (computed as rate in Bps/r2q). КМК, нам это не надо, мы этим никогда не пользовались. Единственное: мы раньше не пользовались DRR, а сейчас я хочу на этом построить Basic QoS.**UPD:** Это можно в глобальной конфигурации задать.
+ `debug` — Какой-то "string of 16 numbers each 0-3", в душе не знаю, что это. + `debug` — Какой-то "string of 16 numbers each 0-3", в душе не знаю, что это.
+ `direct_qlen` — Лимит прямой очереди в штуках пакетов. Мы этим вряд ли воспользуемся, т.к. у нас нет такого сценария, что какой-то пакет нужной пропускать мимо QoS. Ну, я таких сценариев не знаю. + `direct_qlen` — Лимит прямой очереди в штуках пакетов. Мы этим вряд ли воспользуемся, т.к. у нас нет такого сценария, что какой-то пакет нужной пропускать мимо QoS. Ну, я таких сценариев не знаю.**UPD:** В целом, можно вписать в мою архитектуру, если явно отобразить такой узел в дереве: будет класс, который матчит весь трафик (как в Complex QoS `class-default`), и в качестве дочернего узла у него некий DirectNode.
+ `offload` — Включение аппаратного QoS. У нас сейчас точно нигде поддержки нет. Вроде бы в новом SDK появилась какая-то поддержка на каких-то платформах Marvell. Для абстрактного дерева эта опция не подходит. + `offload` — Включение аппаратного QoS. У нас сейчас точно нигде поддержки нет. Вроде бы в новом SDK появилась какая-то поддержка на каких-то платформах Marvell. Для абстрактного дерева эта опция не подходит.
Из классов: Из классов:
@@ -77,8 +77,10 @@ Random Early Detection.
Тут вводится понятие "виртуальной очереди" (VQ). И к самому Linux TC оно отношения не имеет. Оно даже к очередям отношение имеет опосредованное: никакой очереди фактически не выделяется, поэтому она и *виртуальная*. И настройка этих очередей довольно виктимная: нужно послать `CHANGE` на уже созданную дисциплину и в качестве параметра передать номер очереди, настройки которой мы хотим изменить. Тут вводится понятие "виртуальной очереди" (VQ). И к самому Linux TC оно отношения не имеет. Оно даже к очередям отношение имеет опосредованное: никакой очереди фактически не выделяется, поэтому она и *виртуальная*. И настройка этих очередей довольно виктимная: нужно послать `CHANGE` на уже созданную дисциплину и в качестве параметра передать номер очереди, настройки которой мы хотим изменить.
+ `vqs` — Кол-во виртуальных очередей. (обязательно) В этом проекте присутствует как узел WRED. Узел WRED несёт в себе только глобальные настройки дисциплины. Для конфигурирования VQ к узлу WRED прикрепляются узлы RED.
+ `default` — Виртуальная очередь по умолчанию. (обязательно)
+ `vqs` — Кол-во виртуальных очередей. (обязательно) — **UPD:** Вообще, нам это не нужно: мы и так можем посчитать, сколько VQ мы определили, по самим дочерним узлам.
+ `default` — Виртуальная очередь по умолчанию. (обязательно) — **UPD:** Это тоже не нужно, т.к. мы фильтрами на самой очереди скажем, что она дефолтная.
+ `grio` — Вкл. наследование буферов. Условно, приоритетный трафик затрагивает, в том числе, счётчики менее приоритетного трафика. + `grio` — Вкл. наследование буферов. Условно, приоритетный трафик затрагивает, в том числе, счётчики менее приоритетного трафика.
+ `limit` — Размер буфера, байты. Здесь, в отличие от RED и VQ, является необязательным. Ограничивает очередь *мимо* VQ, а также задаёт верхнюю планку для каждой VQ (больше этого `limit` нельзя задавать `limit` для VQ). + `limit` — Размер буфера, байты. Здесь, в отличие от RED и VQ, является необязательным. Ограничивает очередь *мимо* VQ, а также задаёт верхнюю планку для каждой VQ (больше этого `limit` нельзя задавать `limit` для VQ).
+ `ecn` — Возможность включить маркировку пакетов на всю дисциплину, либо включение только для отдельной VQ. Вроде бы, и там, и тут включить нельзя. Кроме того, на 4.14, например, эти флаги на VQ вообще не используются. + `ecn` — Возможность включить маркировку пакетов на всю дисциплину, либо включение только для отдельной VQ. Вроде бы, и там, и тут включить нельзя. Кроме того, на 4.14, например, эти флаги на VQ вообще не используются.
@@ -110,3 +112,5 @@ Random Early Detection.
+ `headdrop` — Флаг для отбрасывания трафика из головы очереди, а не с хвоста. Гипотетически, так отклик TCP лучше. + `headdrop` — Флаг для отбрасывания трафика из головы очереди, а не с хвоста. Гипотетически, так отклик TCP лучше.
+ `redflowlimit` — Ограничение в байтах на очередь **потока**. Заодно включает сам RED на каждом потоке SFQ. Да, но мы этим тоже не пользуемся. + `redflowlimit` — Ограничение в байтах на очередь **потока**. Заодно включает сам RED на каждом потоке SFQ. Да, но мы этим тоже не пользуемся.
+ Параметры RED третий раз перечислять не очень-то хочется. Но тут поддерживаются все параметры из [[#RED]], кроме `adaptive`. + Параметры RED третий раз перечислять не очень-то хочется. Но тут поддерживаются все параметры из [[#RED]], кроме `adaptive`.
Параметры RED на SFQ конфигурируются аналогично WRED и VQ: к SFQ подключается RED, с которого и будет считываться конфигурация per-flow RED.