Wheelhouse docs

QoS#

Network → QoS shows what the configuration asks for and what the kernel is really doing, side by side, and offers one editor: a CAKE policy attached as egress on one interface. It writes four kinds of line into the qos subtree and nothing else. If the config asks for CAKE and the kernel reports fq_codel, the page says so in amber instead of drawing a green badge over the disagreement.

The header carries a Policies / CLI toggle and a + CAKE policy button. The CLI view is GET /api/config/commands?path=qos — the whole shaping configuration as set commands, which is the copy you paste into a ticket.

Where the two halves come from#

HalfEndpointRouter command behind it
What is configuredGET /api/qosretrieve of the qos subtree
What is installedGET /api/qos/stats, polled every 4 sshow interfaces <kind> <name> per shaped interface

handleQosStats is worth understanding, because it is the reason the page is honest about non-ethernet interfaces. For each interface named under qos interface it first tries show interfaces ethernet <name>; when that fails it looks the interface's real kind up in the configuration and asks again. A shaped bond, bridge, VLAN or WireGuard tunnel is not an ethernet node, and asking for the wrong one reported "no qdisc" for a shaper that was running — handleQosStats in agent/main.go, with the kind lookup in agent/opmode.go.

From the parsed detail it takes three things: the qdisc name, and the transmit and receive counters.

The attachment panels#

One panel per interface named under qos interface:

RowMeaning
Egress policyThe policy name attached to the outbound direction.
Ingress policyThe policy name attached inbound, if any.
Kernel qdiscWhat the kernel reports on that interface right now, or unknown.
TX bytes / TX dropped / RX bytesCounters from the same read.

The title carries a badge with the kernel's qdisc. When the configured policy's kind and the kernel's qdisc disagree, that badge turns amber and a drift badge appears beside it naming both: "config asks for cake, kernel reports fq_codel". Drift here almost always means the commit that attached the policy did not take, or something outside the configuration re-attached a qdisc.

Below the attachments, one panel per policy kind (cake, shaper, fq-codel, whatever the tree holds), listing each policy by name with every field it declares. Those panels render whatever is in the configuration — they are not limited to what the editor can write.

The editor#

+ CAKE policy opens a side panel; Edit on an attachment opens the same panel pre-filled from that interface's existing egress policy. Four inputs:

FieldDefault in the formWhat it writes
Policy nameWAN-OUT (hidden when editing an existing attachment)the policy's node name
Interfaceeth1 (hidden when editing an attachment)which interface the policy attaches to
Bandwidth70mbitbandwidth <value>
Flow isolationdual-src-hostflow-isolation <value>
RTT (ms)100rtt <value>

Flow isolation is a fixed list: flow, dual-src-host, dual-dst-host, src-host, dst-host, host, triple-isolate.

The panel shows the exact commands before you stage them, and staging them puts them in the Commit Bar like any other change. For the defaults above:

set qos policy cake WAN-OUT bandwidth 70mbit
set qos policy cake WAN-OUT flow-isolation dual-src-host
set qos policy cake WAN-OUT rtt 100
set qos interface eth1 egress WAN-OUT

Detach — offered only when you opened the panel from an existing attachment — stages a single operation:

delete qos interface eth1

That removes the attachment and leaves the policy definition in the tree, so you can re-attach it without retyping it. To remove the policy itself, delete qos policy cake <name> from the Config tree page or the CLI.

The empty state#

A router with nothing under qos shows one panel with three commands, which are the whole minimum configuration:

set qos policy cake WAN-OUT bandwidth 70mbit
set qos policy cake WAN-OUT flow-isolation dual-src-host
set qos interface eth1 egress WAN-OUT

What the editor does not write#

This matters more than the list of what it does, because the product's own plan asks for more than has shipped.

Also absent: per-class or per-host bandwidth limits from this page, a priority-queue editor, and any measurement of the link the shaper is on. The page never tests your line rate; the number in the form is the number you typed.

Integration offers on this page#

If an installed app declares a hint for the qos page it appears here as a card under the header. The catalogue ships one: Speedtest Tracker offers "Set the shaper from measured throughput", which is advice, not commands — it carries no operations, so there is no Stage this change button on it. How hints work is on Apps — integration offers.

Checking it from the CLI#

The two reads the page makes, by hand:

show configuration commands | match qos
show interfaces ethernet eth1

The second one's qdisc field is what the Kernel qdisc row shows.

See also#


Checked against ui/src/pages/Qos.tsx, agent/main.go, agent/opmode.go, ui/src/lib/format.ts, agent/catalog.json, PLAN.md.

Updated 2026-09-02 manual qos cake shaping