8.4 KiB
Topology Data Flow
This page is the canonical reference for how topology and shaping data move through LibreQoS.
It answers 3 questions:
- Where does topology/shaping data enter the system?
- Which files are logical source of truth versus runtime outputs?
- Which UI/runtime components consume each layer?
High-Level Flow
flowchart LR
subgraph Integration Ingress
I0[UISP / Splynx / other built-in integrations]
I1[topology_import.json]
I0 --> I1
end
subgraph DIY Ingress
D0[Operator / external scripts]
D1[network.json]
D2[ShapedDevices.csv]
D0 --> D1
D0 --> D2
end
subgraph Logical Topology
L1[topology_canonical_state.json]
L2[topology_editor_state.json]
TM[Topology Manager]
end
subgraph Runtime Queue Topology
R0[lqos_topology]
R1[topology_effective_state.json]
R2[network.effective.json]
R3[shaping_inputs.json]
end
subgraph Runtime Consumers
C1[tree.html / Site Map / Sankey]
C2[lqos_scheduler / Bakery / TC]
end
I1 --> L1
D1 --> L1
L1 --> L2
L2 --> TM
L1 --> R0
L2 --> R0
D2 --> R0
R0 --> R1
R0 --> R2
R0 --> R3
R2 --> C1
R3 --> C2
Logical vs Queue-Visible Topology
LibreQoS now intentionally separates logical topology from queue-visible topology.
Topology Managerworks on the logical topology.tree.html,Site Map,Sankey,shaping_inputs.json, and HTB/Bakery use the queue-visible runtime topology.
That split is what allows:
- roots to remain manageable in Topology Manager without becoming artificial HTB choke points
- static virtual nodes to remain visible for monitoring while staying out of the physical queue tree
- transport/backhaul paths to remain manageable logically while being squashed for queueing
flowchart TD
A[Logical Topology] --> B[topology_canonical_state.json]
B --> C[topology_editor_state.json]
C --> D[Topology Manager]
B --> E[lqos_topology]
C --> E
E --> F[Runtime Queue Policy]
F --> G[Static virtualization / root promotion]
G --> H[Runtime squashing]
H --> I[network.effective.json]
H --> J[shaping_inputs.json]
I --> K[tree.html / Site Map / Sankey]
J --> L[Bakery / TC / Scheduler]
Integration vs DIY Modes
Integration Mode
Built-in integrations own the imported topology and shaping facts.
topology_import.jsonis the ingress artifact.network.jsonis not the source of truth in this mode.Topology Manageredits logical topology on top of imported data.lqos_topologycompiles runtime outputs from the logical state.
DIY / Manual Mode
Operator-managed files remain the ingress contract.
network.jsonis the topology ingress file.ShapedDevices.csvis the shaping ingress file.lqos_topologystill produces the same runtime outputs:network.effective.jsonshaping_inputs.json
For DIY/manual deployments that expect the Parent Node column in ShapedDevices.csv to shape under named nodes from network.json, use a hierarchy-preserving topology mode such as:
[topology]
compile_mode = "full"
Do not use compile_mode = "flat" for hierarchy-based parent shaping. Flat mode intentionally assigns circuits to generated CPU bucket queues such as Generated_PN_1; shaping_inputs.json will show resolution_source: "flat_bucket" for those circuits.
flowchart LR
A[Built-in Integration Mode] --> B[topology_import.json]
B --> C[topology_canonical_state.json]
C --> D[lqos_topology]
D --> E[network.effective.json]
D --> F[shaping_inputs.json]
G[DIY / Manual Mode] --> H[network.json]
G --> I[ShapedDevices.csv]
H --> C
I --> D
File Roles
| File | Producer | Main consumer | Role | Authoritative in integration mode | Authoritative in DIY mode | Operator editable |
|---|---|---|---|---|---|---|
topology_import.json |
built-in integrations | topology compiler / runtime | integration ingress | Yes | No | No |
network.json |
operator or external scripts | canonical import fallback / DIY ingress | DIY/manual topology ingress | No | Yes | Yes |
ShapedDevices.csv |
operator or external scripts | shaping ingress | DIY/manual shaping ingress | No | Yes | Yes |
topology_canonical_state.json |
compiler / runtime prep | lqos_topology |
logical canonical topology | Internal source of truth | Internal source of truth | No |
topology_editor_state.json |
compiler / runtime prep | Topology Manager | logical editable topology | Internal source of truth | Internal source of truth | No |
topology_effective_state.json |
lqos_topology |
runtime diagnostics | resolved logical/effective attachment state | Runtime output | Runtime output | No |
network.effective.json |
lqos_topology |
tree/UI/runtime consumers | queue-visible runtime topology | Yes | Yes | No |
shaping_inputs.json |
lqos_topology |
scheduler / Bakery / TC | shaping-ready runtime input | Yes | Yes | No |
lqos_overrides.json |
operator / WebUI / CLI | scheduler / topology runtime | durable operator intent | Yes | Yes | Yes |
topology_attachment_health_state.json |
topology probes | Topology Manager / debug pages | runtime attachment health | Runtime state | Runtime state | No |
Runtime Fallback Warnings
When a circuit references a parent or anchor that is not present in the queue-visible effective topology, LibreQoS still shapes the circuit under a generated parent node. Scheduler output summarizes those fallbacks by reason and includes a few example circuits instead of printing one warning per circuit. Review the examples in Topology Manager or the source integration when those circuits should attach to a specific real site, AP, or parent node.
This is different from explicit flat mode. If shaping_inputs.json shows resolution_source: "flat_bucket", the generated parent node is expected flat-mode behavior. Switch topology.compile_mode away from flat when circuits should follow network.json parent names.
Consumer Map
flowchart LR
A[topology_editor_state.json] --> B[Topology Manager]
C[network.effective.json] --> D[Network Tree Overview]
C --> E[Site Map]
C --> F[Tree Overview Sankey]
G[shaping_inputs.json] --> H[lqos_scheduler]
H --> I[lqos_bakery]
I --> J[Linux TC / HTB]
Topology Manager Persistence Flow
Topology Manager edits are overlay intent. They do not replace imported topology facts at the source; they persist as operator intent and are reapplied on top of refreshed topology.
flowchart LR
A[Topology Manager edit] --> B[lqos_overrides.json]
B --> C[lqos_scheduler refresh]
C --> D[topology_editor_state.json]
C --> E[lqos_topology]
E --> F[network.effective.json]
E --> G[shaping_inputs.json]
G --> H[lqos_bakery]
H --> I[Linux TC / HTB]
What this means:
- A saved move or attachment preference survives later integration refreshes.
- Imported topology remains the base data set; operator intent is reapplied on top.
- Bakery and TC are driven from regenerated runtime outputs, not directly from the Topology Manager page.
Key Rules
- Topology Manager uses logical topology, not the queue tree.
network.effective.jsonis the queue-visible runtime tree.shaping_inputs.jsonis the shaping-ready runtime contract for scheduler/Bakery/TC.- Runtime consumers should prefer active runtime outputs such as
shaping_inputs.json; ingress files such asShapedDevices.csvandtopology_import.jsonare upstream inputs and fallback sources when runtime outputs are not yet ready. - In built-in integration mode,
network.jsonandShapedDevices.csvare not the working source of truth. - Compatibility or legacy tree artifacts are downstream-only in integration mode.
- Static virtual nodes remain visible logically/runtime for monitoring, but they do not consume physical HTB classes.
- Runtime squashing removes queue-useless transport hops from the queue-visible tree while preserving logical manageability elsewhere.
- Topology Manager saves operator intent as overlay state; runtime outputs are regenerated from imported topology plus overrides.