fix(qos): harmonize SQM and CAKE cooperation, resolve bufferbloat degradation

This commit is contained in:
Dushnilin
2026-09-14 17:03:45 +03:00
parent 24c11bbca8
commit 7375e26b44
11 changed files with 249 additions and 36 deletions
@@ -2774,6 +2774,67 @@ function run_doctor_checks_impl(repair) {
}
}
// 4b3. SQM (Smart Queue Management) & Bufferbloat compatibility
let sqm_queues = uci_core.section_objects("sqm", "queue");
let sqm_enabled_count = 0;
let sqm_lan_bridge_conflict = null;
let lan_bridge_ports = [];
let br_lan_ports = uci_core.get("network.br_lan.ports") || uci_core.get("network.lan.ports") || [];
if (type(br_lan_ports) == "string") br_lan_ports = split(br_lan_ports, /\s+/);
if (type(br_lan_ports) == "array") {
for (let p in br_lan_ports) push(lan_bridge_ports, as_string(p));
}
push(lan_bridge_ports, "br-lan");
if (sqm_queues && length(sqm_queues) > 0) {
for (let q in sqm_queues) {
if (q && (q.enabled == "1" || q.enabled == true)) {
sqm_enabled_count++;
let q_iface = as_string(q.interface || "");
for (let bp in lan_bridge_ports) {
if (q_iface == bp && bp != "") {
sqm_lan_bridge_conflict = q_iface;
break;
}
}
}
}
}
if (sqm_enabled_count > 0) {
let flow_offload = uci_core.get("firewall.@defaults[0].flow_offloading");
if (flow_offload == "1" || flow_offload == "true") {
issues++;
if (!DOCTOR_REPAIR_MODE) {
doc_plan("uci set firewall.@defaults[0].flow_offloading='0' + firewall reload");
doc_check("⚠️", "SQM / Flow Offloading", "conflict (flow offload bypasses SQM queues)",
"→ WILL FIX (doctor --fix): отключение flow_offloading для устранения bufferbloat");
} else {
doc_set("firewall.@defaults[0].flow_offloading", "0");
doc_commit("firewall");
command_status("/etc/init.d/firewall reload >/dev/null 2>&1");
command_status("sleep 1");
let fo2 = uci_core.get("firewall.@defaults[0].flow_offloading");
if (fo2 != "1" && fo2 != "true") {
doc_check("❌", "SQM / Flow Offloading", "conflict", "→ FIXED: flow_offloading=0 (SQM bufferbloat восстановлен)");
fixed++;
} else {
doc_check("❌", "SQM / Flow Offloading", "conflict", "→ не удалось отключить flow_offloading");
}
}
} else {
doc_check("✅", "SQM / Flow Offloading", "compatible (flow_offloading=0)", "");
}
if (sqm_lan_bridge_conflict != null) {
issues++;
doc_check("⚠️", "SQM interface (" + sqm_lan_bridge_conflict + ")", "misconfigured on LAN bridge",
"→ Привяжите очередь SQM к WAN интерфейсу (pppoe-wan/wan)");
} else {
doc_check("✅", "SQM (CAKE/fq_codel)", "active (QoS cooperative mode)", "");
}
}
// 4c. Resolv.conf symlink
let resolv_link = "";
// Throws when /etc/resolv.conf is a regular file rather than a symlink,
+8 -3
View File
@@ -1700,7 +1700,8 @@ function nft_create_runtime_base(table, localv4_set, common_set, port_set, ip_po
// QoS Low-Latency Gaming & Voice Acceleration Engine
let qos_setting = uci_settings().qos_priority_engine;
let qos_enabled = (qos_setting == "1" || (qos_setting != "0" && !sqm_service_enabled()));
let sqm_active = sqm_service_enabled();
let qos_enabled = (qos_setting == "1" || qos_setting != "0");
if (qos_enabled) {
// Voice & Discord RTC (DSCP EF 0x2e)
@@ -1711,8 +1712,12 @@ function nft_create_runtime_base(table, localv4_set, common_set, port_set, ip_po
nft_add_rule(table, "mangle_forward", [ "udp", "dport", "{ 3074, 7000-9000, 27000-27050, 28960 }", "ip", "dscp", "set", "0x22" ]);
nft_add_rule(table, "mangle_output", [ "udp", "dport", "{ 3074, 7000-9000, 27000-27050, 28960 }", "ip", "dscp", "set", "0x22" ]);
// Pure TCP ACK Acceleration (DSCP CS2) - only small packets without payload
nft_add_rule(table, "mangle_forward", [ "tcp", "flags", "&", "(fin|syn|rst|ack)", "==", "ack", "meta", "length", "<=", "64", "ip", "dscp", "set", "cs2" ]);
// Pure TCP ACK Acceleration (DSCP CS2) - only small packets without payload.
// When SQM (CAKE) is active, CAKE's built-in ack-filter handles ACKs natively,
// and setting CS2 on ACKs pollutes CAKE's Video tin (Tin 2) in diffserv4.
if (!sqm_active) {
nft_add_rule(table, "mangle_forward", [ "tcp", "flags", "&", "(fin|syn|rst|ack)", "==", "ack", "meta", "length", "<=", "64", "ip", "dscp", "set", "cs2" ]);
}
}
return true;
@@ -722,19 +722,6 @@ function controller(bus, opts) {
let qos_pref = setting("qos_priority_engine", "");
if (qos_pref == "0") return;
if (qos_pref != "1") {
let queues = uci_core.section_objects("sqm", "queue");
let sqm_on = false;
if (queues && length(queues) > 0) {
for (let q in queues) {
if (q.enabled == "1" || q.enabled == true) {
sqm_on = true;
break;
}
}
}
if (sqm_on) return;
}
if ((index(out_nft, "dscp set 0x2e") < 0 && index(out_nft, "dscp set ef") < 0) ||
(index(out_nft, "dscp set 0x22") < 0 && index(out_nft, "dscp set af41") < 0))
bus.emit(EV.QOS_MISSING, { table: nft_table });