Files
LibreQoS/docs/v2.0/topology-data-flow.md
T
2026-05-30 00:00:30 -06:00

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:

  1. Where does topology/shaping data enter the system?
  2. Which files are logical source of truth versus runtime outputs?
  3. 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 Manager works 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.json is the ingress artifact.
  • network.json is not the source of truth in this mode.
  • Topology Manager edits logical topology on top of imported data.
  • lqos_topology compiles runtime outputs from the logical state.

DIY / Manual Mode

Operator-managed files remain the ingress contract.

  • network.json is the topology ingress file.
  • ShapedDevices.csv is the shaping ingress file.
  • lqos_topology still produces the same runtime outputs:
    • network.effective.json
    • shaping_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.json is the queue-visible runtime tree.
  • shaping_inputs.json is the shaping-ready runtime contract for scheduler/Bakery/TC.
  • Runtime consumers should prefer active runtime outputs such as shaping_inputs.json; ingress files such as ShapedDevices.csv and topology_import.json are upstream inputs and fallback sources when runtime outputs are not yet ready.
  • In built-in integration mode, network.json and ShapedDevices.csv are 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.