We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, religion, or sexual identity
+and orientation.
+
We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official e-mail address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement at
+robert@libreqos.io.
+All complaints will be reviewed and investigated promptly and fairly.
+
All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
Community Impact: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
Consequence: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
Community Impact: A violation through a single incident or series
+of actions.
+
Consequence: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or
+permanent ban.
Community Impact: A serious violation of community standards, including
+sustained inappropriate behavior.
+
Consequence: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
Community Impact: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior, harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
Consequence: A permanent ban from any sort of public interaction within
+the community.
This Code of Conduct is adapted from the Contributor Covenant,
+version 2.0, available at
+https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
For answers to common questions about this code of conduct, see the FAQ at
+https://www.contributor-covenant.org/faq. Translations are available at
+https://www.contributor-covenant.org/translations.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/CONTRIBUTING.html b/_build/html/CONTRIBUTING.html
new file mode 100644
index 00000000..9fb932c2
--- /dev/null
+++ b/_build/html/CONTRIBUTING.html
@@ -0,0 +1,334 @@
+
+
+
+
+
+
+
+
+ Contributing to LibreQoS — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
So your interested in contributing to LibreQoS! Awesome! Feel free to pitch in with whatever interests you, and we’ll be happy to help.
+
Check out our Code of Conduct, we’d like to keep this a happy, constructive place. Also, please join the chat on Matrix—the core developers hang out there, and will be happy to help you.
+
In particular:
+
+
We can check that an issue isn’t already being worked on. There’s nothing more frustrating than working hard on an issue only to discover that someone else already fixed it!
+
We can help point you at issues that might interest you.
+
We can offer help and/or mentoring with Rust and C.
Battle-Testing LibreQos: use the software, let us know what does/doesn’t work!
+
Donate: it’s free software, but we appreciate your support.
+
Let us Know Your Thoughts: Hop on the chat or our discussions page and let us know what you’re thinking about.
+
Finding Bugs - something doesn’t work for you? We can’t fix it if you don’t tell us about it.
+
Fixing Bugs and Adding Features: See the “Development Guide”, below.
+
Teaching Others: if LibreQoS is working well for you, you can help others benefit by sharing your experience. See someone struggling? Feel free to pitch in and help them.
+
+
LibreQos strive to create an open, friendly environment. If you have an idea for how to help, let us know.
lqosd is probably the most important part of the Rust system. It loads the eBPF system that provides bridging and traffic shaping control, runs the “bus” for other systems to communicate, and gathers information directly from the eBPF and kernel systems. It has several sub-crates:
+
+
lqos_heimdall handles all of the packet sniffing, flow tracking and libcap compatible packet data.
+
lqos_queue_tracker maintains statistics for Linux tc shaping queues, particularly Cake.
+
+
+
lqos_node_manager provides a per-node management web interface. It gathers most of its data from lqosd via the bus.
+
+
+
CLI Utilities
+
+
lqusers provides a CLI interface for managing authentication to the node manager.
+
lqtop provides a quick and easy way to see what the shaper is doing from the local management console.
+
xdp_iphash_to_cpu_cmdline (the name is inherited from previous projects) provides a command-line interface to map IP subnets to TC and CPU handles.
+
xdp_pping provides a CLI tool to give a quick summary of TCP RTT times, grouped by TC handle.
+
+
+
Libraries
+
+
lqos_bus provides a local-only (never leaving the shaper node) inter-process communication system. It’s used by programs that need to ask lqosd to do something, or retrieve information from it.
+
+
The lqos_bus crate also acts as a repository for shared data structures when data is passed between portions of the program.
+
+
+
lqos_config manages Rust integration with the ispConfig.py configuration file, and the /etc/lqos.conf file. It is designed as a helper for other systems to quickly access configuration parameters.
+
lqos_python compiles into a Python loadable library, providing a convenient interface to Rust code from the Python portions of the program.
+
lqos_setup provides a text-based initial setup system for users who install LibreQoS via apt-get.
+
lqos_utils provides a grab-bag of handy functions we’ve found useful elsewhere in the system.
+
+
+
+
+
Python: system operation and integration
+
+
LibreQoS.py maps all circuits to TC handles and gets the shaper system running.
+
ispConfig.py provides a system-wide configuration.
+
integrationX.py provide integrations with UISP, Splynx and other CRM tools.
+
lqTools.py provides an interface for gathering statistics.
When we use the word “agile”, we don’t mean the heavily formalized process with scrums, kanban boards and similar. We mean lightweight, fast moving, and adhering to useful guides like “Code Complete” and “The Pragmatic Programmer”. Not getting bogged down in heavy process.
Let us know on the chat that you’re working on it.
+
Create an Issue in our GitHub repo.
+
Submit a PR, following the Branch Guidelines below.
+
+
+
Other community members review and comment on your change in an informal manner.
+
Once consensus is reached, we’ll merge to the develop branch (or a branch parented from develop if it’s a big change) and test it on our server resources at Equinix.
If you need/want a complicated change, please get in touch with us on the Matrix chat first. We’d like to avoid duplicating effort and wasting anyone’s time. We’ll be happy to offer advice and guidance. Then the process is similar:
+
+
Work on your local branch, parented off of develop.
+
Create a PR (targeting develop). If you’d like interim feedback, create a “draft PR” and we can help test your branch before the PR finalizes.
+
Once your PR is ready, submit it.
+
The community will review/comment on your PR.
+
Once consensus is reached, we’ll merge it into develop.
LibreQoS has adopted the following scheme for branches:
+
+
main - released code (tagged at releases), safe to pull.
+
+
develop - Parented from main and rebased on release. Nothing gets directly comitted into develop, it’s the parent tree for ongoing development work.
+
+
my_feature - if you’re working on a feature, your feature branch goes here - with develop as the parent. PRs—once the feature is ready for inclusion—should be targeted at develop.
+
issue_xxx_name - if you’re working on a bugfix, work on it in a branch here. When the issue resolution is complete, PRs should be targeted at develop.
+
+
+
hotfix_xxx - If an emergency occurs and you have to push a fix to main in a hurry, hotfix branches can be parented from main. The resulting PR should target main. Let the developers know that they need to rebase develop.
+
+
+
+
The goal is for main to always be safe to clone and run, without surprises.
Don’t use short, incomprehensible names in any API or function accessible from outside. You don’t save any RAM by naming your variable sz instead of size—you just make it harder for anyone reading the code.
+
It’s fine to use i and similar for internal counting iterators. Try to use meaningful names for everything else.
Prefer functional/iterative code to imperative. Sometimes you need a for loop, but if it can be replaced with an iter, map and fold it will both compile into faster code and be less error prone.
+
It’s better to have lots of small functions than one big one. Rust is really good at inlining, and it’s much easier to understand short functions. It’s also easier to test small functions.
+
If you have to override a Clippy warning, add a comment explaining why you did so.
+
Functions accessible from other crates should use the RustDoc standard for documentation.
Use thiserror to emit readable error messages from your functions.
+
It’s fine to use ? and anyhow inside function chains; prefer result.map_err to transform your errors into your own errors whenever it’s possible that an error can be returned from a function accessible beyond the immediate crate.
+
Issue a log::error! or log::warn! messaage when an error occurs. Don’t trust the callee to do it for you. It’s better to have duplicate error messages than none at all.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/README.html b/_build/html/README.html
new file mode 100644
index 00000000..db65eeb2
--- /dev/null
+++ b/_build/html/README.html
@@ -0,0 +1,181 @@
+
+
+
+
+
+
+
+
+ Sponsors — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
LibreQoS is software used by Internet Service Providers (ISPs) and Enterprises to improve the Quality of Experience (QoE) of end-users on their networks.
+
LibreQoS works by monitoring network performance and reducing latency for interactive online applications. ISPs regularly report that trouble calls reduce substantially after deploying LibreQoS on networks.
+
For an ISP or other company to deploy LibreQoS – no changes are required for existing Routers, Switches or Access points: LibreQoS runs on a server that acts as a managed bridge sitting between the edge router and the core of the network. LibreQoS servers can shape traffic for tens of thousands of customers.
+
LibreQoS benefits network operation and planning by measuring metrics such as end-to-end TCP round trip time for each Subscriber, Access Point, and Site on a network – saving the relevant data for later analysis in the LibreQoS Insight system.
+
LibreQoS code is Open Source. It improves Quality of Experience by implementing state of the art Flow Queueing (FQ) and Active Queue Management (AQM) algorithms. LibreQoS offers paid support packages and subscriptions to additional analysis service features available through LibreQoS Insight.
LibreQoS’ development is made possible by our sponsors, the NLnet Foundation and Equinix.
+
LibreQoS has been funded through the NGI0 Entrust Fund, a fund established by NLnet with financial support from the European Commission’s Next Generation Internet programme, under the aegis of DG Communications Networks, Content and Technology under grant agreement No 101069594. Learn more at https://nlnet.nl/project/LibreQoS/
+
Equinix supports LibreQoS through its Open Source program – providing access to hardware resources on its Equinix Metal infrastructure. Equinix’ support has been crucial for LibreQoS to scale past 10Gbps for higher-bandwidth networks. Learn more about Equinix Metal here.
+Learn more about Equinix Metal here.
+
+
+
Documentation / Get Started / System Requirements
LibreQoS Insight is the successor to our Long Term Stats (LTS) service. Insight was designed from the ground up to accommodate multi-shaper networks, providing high-resolution data on TCP Round Trip Time, TCP Retransmits, Throughput, Flows, ASN Stats, CAKE stats, Geographic Endpoint stats, as well as data on protocol, ethertype, and utilization percentages.
+
Insight allows you to thoroughly monitor your network both at high-level, as well as to drill down to monitor the performance of individual subscribers, Access Points, OLTs, Sites, and even entire network segments. With powerful metrics such as TCP Retransmits, you can track and resolve subtle network issues before customers notice them at all.
+
Insight provides a free 30-day trial to allow network operators to see its powerful capabilities firsthand. Learn more about Insight here.
Dave served as LibreQoS’ Chief Science Officer and championed the global fight against bufferbloat. You can learn more about Dave’s incredible legacy here, and learn how our team is working to carry on his mission.
We can only accept PRs that address one specific change or topic each. We ask that you keep all changes small and focused per-PR to help our review and testing process.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/_images/network_new.png b/_build/html/_images/network_new.png
new file mode 100644
index 00000000..245a380f
Binary files /dev/null and b/_build/html/_images/network_new.png differ
diff --git a/_build/html/_sources/.github/CODE_OF_CONDUCT.md.txt b/_build/html/_sources/.github/CODE_OF_CONDUCT.md.txt
new file mode 100644
index 00000000..30b0cc77
--- /dev/null
+++ b/_build/html/_sources/.github/CODE_OF_CONDUCT.md.txt
@@ -0,0 +1,128 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, religion, or sexual identity
+and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+ and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the
+ overall community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or
+ advances of any kind
+* Trolling, insulting or derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email
+ address, without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official e-mail address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement at
+robert@libreqos.io.
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series
+of actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or
+permanent ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior, harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within
+the community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.0, available at
+https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
+
+Community Impact Guidelines were inspired by [Mozilla's code of conduct
+enforcement ladder](https://github.com/mozilla/diversity).
+
+[homepage]: https://www.contributor-covenant.org
+
+For answers to common questions about this code of conduct, see the FAQ at
+https://www.contributor-covenant.org/faq. Translations are available at
+https://www.contributor-covenant.org/translations.
diff --git a/_build/html/_sources/CONTRIBUTING.md.txt b/_build/html/_sources/CONTRIBUTING.md.txt
new file mode 100644
index 00000000..a8f33fa1
--- /dev/null
+++ b/_build/html/_sources/CONTRIBUTING.md.txt
@@ -0,0 +1,154 @@
+> This is **draft 1** of the contributing guide. Comments/edits appreciated.
+
+# Contributing to LibreQoS
+
+So your interested in contributing to LibreQoS! Awesome! Feel free to pitch in with whatever interests you, and we'll be happy to help.
+
+Check out our [Code of Conduct](https://github.com/LibreQoE/LibreQoS/blob/main/.github/CODE_OF_CONDUCT.md), we'd like to keep this a happy, constructive place. Also, please join the chat on [Matrix](https://app.element.io/#/room/#libreqos:matrix.org)---the core developers hang out there, and will be happy to help you.
+
+In particular:
+
+* We can check that an issue isn't already being worked on. There's nothing more frustrating than working hard on an issue only to discover that someone else already fixed it!
+* We can help point you at issues that might interest you.
+* We can offer help and/or mentoring with Rust and C.
+
+# How You Can Help
+
+There's lots of ways you can help:
+
+* **Battle-Testing LibreQos**: use the software, let us know what does/doesn't work!
+* **Donate**: it's free software, but we appreciate your support.
+* **Let us Know Your Thoughts**: Hop on the chat or our discussions page and let us know what you're thinking about.
+* **Finding Bugs** - something doesn't work for you? We can't fix it if you don't tell us about it.
+* **Fixing Bugs** and **Adding Features**: See the "Development Guide", below.
+* **Teaching Others**: if LibreQoS is working well for you, you can help others benefit by sharing your experience. See someone struggling? Feel free to pitch in and help them.
+
+LibreQos strive to create an open, friendly environment. If you have an idea for how to help, let us know.
+
+# Development Guidelines
+
+This section contains some advice to help get you started writing code for LibreQoS.
+
+## Getting Oriented with LibreQoS
+
+LibreQos is divided into several sections:
+
+* **Rust: system management/control plane**
+ * **System Daemons**
+ * `lqosd` is probably the most important part of the Rust system. It loads the eBPF system that provides bridging and traffic shaping control, runs the "bus" for other systems to communicate, and gathers information directly from the eBPF and kernel systems. It has several sub-crates:
+ * `lqos_heimdall` handles all of the packet sniffing, flow tracking and `libcap` compatible packet data.
+ * `lqos_queue_tracker` maintains statistics for Linux `tc` shaping queues, particularly Cake.
+ * `lqos_node_manager` provides a per-node management web interface. It gathers most of its data from `lqosd` via the bus.
+ * **CLI Utilities**
+ * `lqusers` provides a CLI interface for managing authentication to the node manager.
+ * `lqtop` provides a quick and easy way to see what the shaper is doing from the local management console.
+ * `xdp_iphash_to_cpu_cmdline` (the name is inherited from previous projects) provides a command-line interface to map IP subnets to TC and CPU handles.
+ * `xdp_pping` provides a CLI tool to give a quick summary of TCP RTT times, grouped by TC handle.
+ * **Libraries**
+ * `lqos_bus` provides a local-only (never leaving the shaper node) inter-process communication system. It's used by programs that need to ask `lqosd` to do something, or retrieve information from it.
+ * The `lqos_bus` crate also acts as a repository for shared data structures when data is passed between portions of the program.
+ * `lqos_config` manages Rust integration with the `ispConfig.py` configuration file, and the `/etc/lqos.conf` file. It is designed as a helper for other systems to quickly access configuration parameters.
+ * `lqos_python` compiles into a Python loadable library, providing a convenient interface to Rust code from the Python portions of the program.
+ * `lqos_setup` provides a text-based initial setup system for users who install LibreQoS via `apt-get`.
+ * `lqos_utils` provides a grab-bag of handy functions we've found useful elsewhere in the system.
+* **Python: system operation and integration**
+ * `LibreQoS.py` maps all circuits to TC handles and gets the shaper system running.
+ * `ispConfig.py` provides a system-wide configuration.
+ * `integrationX.py` provide integrations with UISP, Splynx and other CRM tools.
+ * `lqTools.py` provides an interface for gathering statistics.
+
+## What We're Building
+
+LibreQoS is a free/open source fair queueing system. It's designed for ISPs, but can be useful elsewhere. Primary goals:
+
+* Provide fair-queueing to help maximize the use of the Internet resources you have.
+* Keep end-user latency low.
+* Don't alter user traffic (for example by lowering the quality of their streaming video).
+* Don't invade user's privacy.
+* Provide excellent support tools to help keep your ISP running smoothly.
+
+Some secondary goals include:
+
+* Visualize data to facilitate moving the state-of-the-art in fair queueing forwards.
+* Provide amazing throughput on inexpensive hardware.
+
+## Making Changes to LibreQoS
+
+We try to remain fast-moving and "process light".
+
+> When we use the word "agile", we don't mean the heavily formalized process with scrums, kanban boards and similar. We mean lightweight, fast moving, and adhering to useful guides like "Code Complete" and "The Pragmatic Programmer". Not getting bogged down in heavy process.
+
+### Simple Changes
+
+For a straightforward change, do the following:
+
+1. Do one (or more!) of the following:
+ * Let us know on the chat that you're working on it.
+ * Create an Issue in our GitHub repo.
+ * Submit a PR, following the Branch Guidelines below.
+2. Other community members review and comment on your change in an informal manner.
+3. Once consensus is reached, we'll merge to the `develop` branch (or a branch parented from `develop` if it's a big change) and test it on our server resources at Equinix.
+4. When ready, we'll merge it into the next release.
+
+### Complex Changes
+
+If you need/want a complicated change, please get in touch with us on the Matrix chat first. We'd like to avoid duplicating effort and wasting anyone's time. We'll be happy to offer advice and guidance. Then the process is similar:
+
+1. Work on your local branch, parented off of `develop`.
+2. Create a PR (targeting `develop`). If you'd like interim feedback, create a "draft PR" and we can help test your branch before the PR finalizes.
+3. Once your PR is ready, submit it.
+4. The community will review/comment on your PR.
+5. Once consensus is reached, we'll merge it into `develop`.
+6. Once ready, `develop` will merge into `main`.
+
+## Branch Guidelines
+
+LibreQoS has adopted the following scheme for branches:
+
+* `main` - released code (tagged at releases), safe to pull.
+ * `develop` - Parented from `main` and rebased on release. Nothing gets directly comitted into `develop`, it's the parent tree for ongoing development work.
+ * `my_feature` - if you're working on a feature, your feature branch goes here - with `develop` as the parent. PRs---once the feature is ready for inclusion---should be targeted at `develop`.
+ * `issue_xxx_name` - if you're working on a bugfix, work on it in a branch here. When the issue resolution is complete, PRs should be targeted at `develop`.
+ * `hotfix_xxx` - If an emergency occurs and you have to push a fix to `main` in a hurry, hotfix branches can be parented from `main`. The resulting PR should target `main`. Let the developers know that they need to rebase `develop`.
+
+The goal is for `main` to *always* be safe to clone and run, without surprises.
+
+## Code Guidelines
+
+This is very much a work in progress.
+
+### Rust
+
+#### Code Formatting
+
+* Use `cargo fmt` to format your code. We've got a customized format setup in place.
+* Adhere to standard Rust case and naming guidelines.
+
+#### Dependencies
+
+* Check that you aren't including any dependencies that incompatible with our license---GPL v2.
+* Look through the `Cargo.toml` files (or run `cargo tree`) and try to prefer using a dependency we use elsewhere.
+* Try to avoid using unmaintained crates.
+
+#### Naming
+
+* Don't use short, incomprehensible names in any API or function accessible from outside. You don't save any RAM by naming your variable `sz` instead of `size`---you just make it harder for anyone reading the code.
+* It's fine to use `i` and similar for internal counting iterators. Try to use meaningful names for everything else.
+
+#### Code Style
+
+* Prefer functional/iterative code to imperative. Sometimes you need a `for` loop, but if it can be replaced with an `iter`, `map` and `fold` it will both compile into faster code and be less error prone.
+* It's better to have lots of small functions than one big one. Rust is really good at inlining, and it's much easier to understand short functions. It's also easier to test small functions.
+* If you have to override a Clippy warning, add a comment explaining why you did so.
+* Functions accessible from other crates should use the RustDoc standard for documentation.
+
+#### Unit Tests
+
+* If you fix an issue, and it's testable: add a unit test to check that we don't regress and suffer from that bug again.
+* If you create a type, write unit tests to test its constraints.
+
+#### Error Handling
+
+* Use `thiserror` to emit readable error messages from your functions.
+* It's fine to use `?` and `anyhow` inside function chains; prefer `result.map_err` to transform your errors into your own errors whenever it's possible that an error can be returned from a function accessible beyond the immediate crate.
+* Issue a `log::error!` or `log::warn!` messaage when an error occurs. Don't trust the callee to do it for you. It's better to have duplicate error messages than none at all.
diff --git a/_build/html/_sources/README.md.txt b/_build/html/_sources/README.md.txt
new file mode 100644
index 00000000..d96d3511
--- /dev/null
+++ b/_build/html/_sources/README.md.txt
@@ -0,0 +1,61 @@
+
+
+
+
+
+LibreQoS is software used by Internet Service Providers (ISPs) and Enterprises to improve the Quality of Experience (QoE) of end-users on their networks.
+
+LibreQoS works by monitoring network performance and reducing latency for interactive online applications. ISPs regularly report that trouble calls reduce substantially after deploying LibreQoS on networks.
+
+For an ISP or other company to deploy LibreQoS – no changes are required for existing Routers, Switches or Access points: LibreQoS runs on a server that acts as a managed bridge sitting between the edge router and the core of the network. LibreQoS servers can shape traffic for tens of thousands of customers.
+
+LibreQoS benefits network operation and planning by measuring metrics such as end-to-end TCP round trip time for each Subscriber, Access Point, and Site on a network – saving the relevant data for later analysis in the LibreQoS Insight system.
+
+LibreQoS code is Open Source. It improves Quality of Experience by implementing state of the art Flow Queueing (FQ) and Active Queue Management (AQM) algorithms. LibreQoS offers paid support packages and subscriptions to additional analysis service features available through [LibreQoS Insight](https://libreqos.io/insight/).
+
+To learn more, please visit [LibreQoS.io](https://libreqos.io/).
+
+
+
+
+## Sponsors
+
+LibreQoS' development is made possible by our sponsors, the NLnet Foundation and Equinix.
+
+LibreQoS has been funded through the NGI0 Entrust Fund, a fund established by NLnet with financial support from the European Commission’s Next Generation Internet programme, under the aegis of DG Communications Networks, Content and Technology under grant agreement No 101069594. Learn more at https://nlnet.nl/project/LibreQoS/
+
+Equinix supports LibreQoS through its Open Source program – providing access to hardware resources on its Equinix Metal infrastructure. Equinix’ support has been crucial for LibreQoS to scale past 10Gbps for higher-bandwidth networks. Learn more about Equinix Metal here.
+Learn more about [Equinix Metal here](https://deploy.equinix.com/metal/).
+
+## Documentation / Get Started / System Requirements
+
+[ReadTheDocs](https://libreqos.readthedocs.io/en/latest/)
+
+## LibreQoS Chat
+
+Our chat server is available at [https://chat.libreqos.io/](https://chat.libreqos.io/).
+
+## LibreQoS Social
+- https://www.youtube.com/@LibreQoS
+- https://www.linkedin.com/company/libreqos/
+- https://www.facebook.com/libreqos
+- https://twitter.com/libreqos
+- https://fosstodon.org/@LibreQoS/
+
+## LibreQoS Insight
+
+LibreQoS Insight is the successor to our Long Term Stats (LTS) service. Insight was designed from the ground up to accommodate multi-shaper networks, providing high-resolution data on TCP Round Trip Time, TCP Retransmits, Throughput, Flows, ASN Stats, CAKE stats, Geographic Endpoint stats, as well as data on protocol, ethertype, and utilization percentages.
+
+Insight allows you to thoroughly monitor your network both at high-level, as well as to drill down to monitor the performance of individual subscribers, Access Points, OLTs, Sites, and even entire network segments. With powerful metrics such as TCP Retransmits, you can track and resolve subtle network issues before customers notice them at all.
+
+Insight provides a free 30-day trial to allow network operators to see its powerful capabilities firsthand. Learn more about Insight [here](https://libreqos.io/insight).
+
+
+
+
+## In Loving Memory of Dave Täht
+Dave served as LibreQoS' Chief Science Officer and championed the global fight against bufferbloat. You can learn more about [Dave's incredible legacy here](https://libreqos.io/2025/04/01/in-loving-memory-of-dave/), and learn how our team is working to [carry on his mission](https://libreqos.io/company/).
+
+## External Pull Request Policy
+
+We can only accept PRs that address one specific change or topic each. We ask that you keep all changes small and focused per-PR to help our review and testing process.
diff --git a/_build/html/_sources/docs-es/index.rst.txt b/_build/html/_sources/docs-es/index.rst.txt
new file mode 100644
index 00000000..da8db1fd
--- /dev/null
+++ b/_build/html/_sources/docs-es/index.rst.txt
@@ -0,0 +1,46 @@
+.. LibreQoS documentation master file - Spanish version
+
+Bienvenido a la documentación de LibreQoS
+==========================================
+
+.. toctree::
+ :maxdepth: 1
+ :caption: Primeros Pasos
+
+ Quickstart (Empieza Aquí)
+ v2.0/design-es
+ v2.0/requirements-es
+ v2.0/prereq-es
+ v2.0/ubuntu-server-es
+ v2.0/bridge-es
+
+.. toctree::
+ :maxdepth: 1
+ :caption: Gestionando LibreQoS (v1.5 a v2.0):
+
+ v2.0/configuration-es
+ v2.0/operating-modes-es
+ v2.0/configuration-advanced-es
+ v2.0/integrations-es
+ v2.0/components-es
+ v2.0/node-manager-ui-es
+ v2.0/stormguard-es
+ v2.0/high-availability-es
+ v2.0/scale-topology-es
+ v2.0/update-es
+ v2.0/troubleshooting-es
+
+.. toctree::
+ :maxdepth: 1
+ :caption: Insight
+
+ v2.0/insight-es
+ v2.0/api-es
+
+.. toctree::
+ :maxdepth: 1
+ :caption: Misceláneo
+
+ v2.0/cake-es
+ v2.0/performance-tuning-es
+ v2.0/extras-es
diff --git a/_build/html/_sources/docs-es/v2.0/Quickstart/configuration.md.txt b/_build/html/_sources/docs-es/v2.0/Quickstart/configuration.md.txt
new file mode 100644
index 00000000..74188f72
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/Quickstart/configuration.md.txt
@@ -0,0 +1,113 @@
+# Configurar LibreQoS
+
+## Archivo de configuración principal
+### /etc/lqos.conf
+
+La configuración de LibreQoS para cada shaper box se almacena en el archivo `/etc/lqos.conf`.
+
+Edite el archivo para que coincida con su configuración
+
+```shell
+sudo nano /etc/lqos.conf
+```
+
+En la sección ```[bridge]``` , cambie `to_internet` y `to_network` para que coincida con sus interfaces de red.
+- `to_internet = "enp1s0f1"`
+- `to_network = "enp1s0f2"`
+
+Luego, si usa Bifrost/XDP, configure `use_xdp_bridge = true` en la misma sección `[bridge]`. Si no está seguro de que lo necesite, le recomendamos dejarlo como `false`.
+
+- Configure downlink_bandwidth_mbps y uplink_bandwidth_mbps para que coincidan con el ancho de banda en Mbps de la conexión a internet de subida/WAN de su red. Puede hacer lo mismo con generated_pn_download_mbps y generated_pn_upload_mbps.
+- to_internet sería la interfaz que da a su enrutador de borde y a la red de Internet en generla
+- to_network sería la interfaz que da a su enrutador central (o red interna puenteada si su red está puenteada)
+
+Nota: Si observa que el tráfico no se está modelando cuando debería, asegúrese de intercambiar el orden de las interfaces y reinicie lqosd, así como lqos_scheduler con ```sudo systemctl restart lqosd lqos_scheduler```.
+
+Después de cambiar cualquier parte de `/etc/lqos.conf`, se recomienda encarecidamente reiniciar siempre lqosd, utilizando `sudo systemctl restart lqosd`. Esto vuelve a analizar cualquier nuevo valor en lqos.conf, haciendo que esos nuevos valores sean accesibles tanto para el lado Rust como para el lado Python del código.
+
+### Integraciones
+
+Más información sobre cómo [configurar integraciones aquí](../TechnicalDocs/integrations.md).
+
+## Jerarquía de red
+### Network.json
+
+Network.json permite a los operadores de ISP definir una topología de red jerárquica o una topología de red plana.
+
+Si planea utilizar las integraciones UISP, Splynx o Netzur integradas, no es necesario que cree un archivo network.json todavía.
+Si planea utilizar la integración UISP integrada, esta se creará automáticamente la primera vez que se ejecute (suponiendo que network.json aún no exista).
+
+Si no va a utilizar una integración, puede definir manualmente el archivo network.json siguiendo el archivo de plantilla: network.example.json
+
+```text
++-----------------------------------------------------------------------+
+| Entire Network |
++-----------------------+-----------------------+-----------------------+
+| Parent Node A | Parent Node B | Parent Node C |
++-----------------------+-------+-------+-------+-----------------------+
+| Parent Node D | Sub 3 | Sub 4 | Sub 5 | Sub 6 | Sub 7 | Parent Node F |
++-------+-------+-------+-------+-------+-------+-------+-------+-------+
+| Sub 1 | Sub 2 | | | | Sub 8 | Sub 9 |
++-------+-------+-------+-----------------------+-------+-------+-------+
+```
+
+Para redes sin nodos principales (sin puntos de acceso o sitios estrictamente definidos), edite el archivo network.json para utilizar una topología de red plana con
+```nano network.json```
+estableciendo el siguiente contenido del archivo:
+
+```json
+{}
+```
+
+#### Ayuda para la conversión de CSV a JSON
+
+Puede utilizar
+
+```shell
+python3 csvToNetworkJSON.py
+```
+
+para convertir manualNetwork.csv en un archivo network.json.
+manualNetwork.csv se puede copiar desde el archivo de plantilla, manualNetwork.template.csv.
+
+Nota: El nombre del nodo principal debe coincidir con el utilizado para los clientes en ShapedDevices.csv.
+
+## Circuitos
+
+LibreQoS configura los dispositivos individuales según sus direcciones IP, que se agrupan en «circuitos».
+
+Un circuito representa el servicio de Internet de un suscriptor de ISP, que puede tener una sola IP asociada (por ejemplo, al enrutador del suscriptor se le puede asignar una sola IPv4 /32) o puede tener varias IP asociadas (tal vez su enrutador tenga asignada una /29 o varias /32)..
+
+LibreQoS sabe cómo configurar estos dispositivos y en qué nodo (AP, sitio, etc.) se encuentran, gracias al archivo ShapedDevices.csv.
+
+### ShapedDevices.csv
+
+El archivo ShapedDevices.csv correlaciona las direcciones IP de los dispositivos con los circuitos (el servicio exclusivo de cada suscriptor de Internet).
+
+A continuación se muestra un ejemplo de una entrada en el archivo ShapedDevices.csv:
+| Circuit ID | Circuit Name | Device ID | Device Name | Parent Node | MAC | IPv4 | IPv6 | Download Min Mbps | Upload Min Mbps | Download Max Mbps | Upload Max Mbps | Comment |
+|------------|--------------|-----------|-------------|-------------|-----|---------------------------|----------------------|-------------------|-----------------|-------------------|-----------------|---------|
+| 10001 | Person Name | 10001 | Device 1 | AP_A | | 100.64.0.2, 100.64.0.8/29 | fdd7:b724:0:100::/56 | 25 | 5 | 155 | 20 | |
+
+Si utiliza una de nuestras integraciones CRM, este archivo se generará automáticamente. Si no utiliza una integración, puede editar el archivo manualmente utilizando la interfaz de usuario web o editando directamente el archivo ShapedDevices.csv a través de la CLI.
+
+#### Edición manual mediante WebUI
+Navegue hasta el WebUI LibreQoS (http://a.b.c.d:9123) y seleccione Configuration > Shaped Devices.
+
+#### Edición manual mediante CLI
+
+- Modifique el archivo ShapedDevices.csv utilizando su editor de hojas de cálculo preferido (LibreOffice Calc, Excel, etc.), siguiendo la plantilla del archivo - ShapedDevices.example.csv
+- Se requiere el ID del circuito. Debe ser una cadena de algún tipo (int está bien, se analiza como cadena). NO debe incluir ningún símbolo numérico (#). Cada circuito necesita un CircuitID único, no se pueden reutilizar. Aquí, circuito significa esencialmente la ubicación del cliente. Si un cliente tiene varias ubicaciones en diferentes partes de su red, utilice un CircuitID único para cada una de esas ubicaciones.
+- Se requiere al menos una dirección IPv4 o IPv6 para cada entrada.
+- El nombre del punto de acceso o del sitio debe configurarse en el campo Nodo principal. El campo Nodo principal puede dejarse en blanco para redes planas.
+- El archivo ShapedDevices.csv le permite establecer el ancho de banda mínimo garantizado y máximo permitido por suscriptor.
+- Las tarifas mínimas permitidas para los Circuitos son de 2 Mbit. El ancho de banda mínimo y máximo deben estar por encima de ese umbral.
+- Recomendación: establezca el ancho de banda mínimo en algo así como 25/10 y el máximo en 1,15 veces la velocidad anunciada en el plan utilizando bandwidthOverheadFactor = 1,15
+ - De esta manera, cuando un punto de acceso alcanza su límite máximo, los usuarios disponen de la capacidad restante del punto de acceso distribuida de forma equitativa entre ellos.
+ - Garantizar un ancho de banda mínimo razonable para cada suscriptor, permitiéndoles utilizar hasta el máximo proporcionado cuando la utilización del punto de acceso sea inferior al 100 %.
+
+Nota sobre los SLA: para los clientes con contratos SLA que les garantizan un ancho de banda mínimo, establezca la tarifa de su plan como el ancho de banda mínimo. De esta forma, cuando un punto de acceso se acerque a su límite máximo, los clientes con SLA siempre obtendrán esa cantidad.
+
+
+
+Una vez completada la configuración, ya está listo para ejecutar la aplicación e iniciar los [Deamons](./services-and-run.md)
diff --git a/_build/html/_sources/docs-es/v2.0/Quickstart/quickstart-libreqos-2.0.md.txt b/_build/html/_sources/docs-es/v2.0/Quickstart/quickstart-libreqos-2.0.md.txt
new file mode 100644
index 00000000..19d70b6d
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/Quickstart/quickstart-libreqos-2.0.md.txt
@@ -0,0 +1,29 @@
+# Install LibreQoS 1.5/2.0
+
+## Step 1 - Validate Network Design Assumptions and Hardware Selection
+
+- [Network Design Assumptions](../../Quickstart/networkdesignassumptions.md)
+- [System Requirements](../../SystemRequirements/Compute.md)
+
+## Step 2 - Complete The Installation Prerequisites
+
+[LibreQoS Installation Prerequisites](quickstart-prereq.md)
+
+## Step 3 - Install LibreQoS
+
+### Download .DEB Package (Recommended Method)
+
+Donwload the latest .deb from [https://libreqos.io/download/](https://libreqos.io/download/).
+
+Unzip the .zip file and transfer the .deb to your LibreQoS box, installing with:
+```
+sudo apt install ./deb_file_name.deb
+```
+
+### Git Install (For Developers Only - Not Recommended)
+
+[Complex Installation](../TechnicalDocs/git-install.md)
+
+## Step 4 - Configure LibreQoS
+
+You are now ready to [Configure](./configuration.md) LibreQoS!
diff --git a/_build/html/_sources/docs-es/v2.0/Quickstart/quickstart-prereq.md.txt b/_build/html/_sources/docs-es/v2.0/Quickstart/quickstart-prereq.md.txt
new file mode 100644
index 00000000..7b4c12b1
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/Quickstart/quickstart-prereq.md.txt
@@ -0,0 +1,109 @@
+# Server Setup - Pre-requisites
+
+Disable hyperthreading on the BIOS/UEFI of your host system. Hyperthreaading is also known as Simultaneous Multi Threading (SMT) on AMD systems. Disabling this is very important for optimal performance of the XDP cpumap filtering and, in turn, throughput and latency.
+
+- Boot, pressing the appropriate key to enter the BIOS settings
+- For AMD systems, you will have to navigate the settings to find the "SMT Control" setting. Usually it is under something like ```Advanced -> AMD CBS -> CPU Common Options -> Thread Enablement -> SMT Control``` Once you find it, switch to "Disabled" or "Off"
+- For Intel systems, you will also have to navigate the settings to find the "hyperthrading" toggle option. On HP servers it's under ```System Configuration > BIOS/Platform Configuration (RBSU) > Processor Options > Intel (R) Hyperthreading Options.```
+- Save changes and reboot
+
+## Install Ubuntu Server
+
+You can download Ubuntu Server 22.04 from here.
+
+1. Boot Ubuntu Server from USB.
+2. Follow the steps to install Ubuntu Server.
+3. If you use a Mellanox network card, the Ubuntu Server installer will ask you whether to install the mellanox/intel NIC drivers. Check the box to confirm. This extra driver is important.
+4. On the Networking settings step, it is recommended to assign a static IP address to the management network interface.
+5. Ensure SSH server is enabled so you can more easily log into the server later.
+6. You can use scp or sftp to access files from your LibreQoS server for easier file editing. Here's how to access via scp or sftp using an [Ubuntu](https://www.addictivetips.com/ubuntu-linux-tips/sftp-server-ubuntu/) or [Windows](https://winscp.net/eng/index.php) machine.
+
+### Choose Bridge Type
+
+There are two options for the bridge to pass data through your two interfaces:
+
+- Option A: Regular Linux Bridge
+- Option B: Bifrost XDP-Accelerated Bridge
+
+The regular Linux bridge is recommended for Nvidia/Mellanox NICs such as the ConnectX-5 series (which have superior bridge performance), and VM setups using virtualized NICs. The Bifrost Bridge is recommended for Intel NICs with XDP support, such as the X520 and X710.
+
+To use the Bifrost bridge, be sure to enable Bifrost/XDP in lqos.conf in the [Configuration](configuration.md) section.
+
+Below are the instructions to configure Netplan, whether using the Linux Bridge or Bifrost XDP bridge:
+
+## Netplan config
+
+### Option A: Netplan config for a regular Linux bridge
+
+Ubuntu Server uses NetPlan, which uses .yaml files in /etc/netplan to determine interface settings.
+Here, we will add a .yaml specifically for LibreQoS - that way it is not overwritten when changes are made to the default .yaml file.
+
+```shell
+sudo nano /etc/netplan/libreqos.yaml
+```
+
+Assuming your interfaces are ens19 and ens20, here is what your file would look like:
+
+```yaml
+network:
+ ethernets:
+ ens19:
+ dhcp4: no
+ dhcp6: no
+ ens20:
+ dhcp4: no
+ dhcp6: no
+ bridges:
+ br0:
+ interfaces:
+ - ens19
+ - ens20
+ version: 2
+```
+```{note}
+Please be sure to replace ens19 and ens20 in the example above with the correct shaping interfaces. The order of the interfaces does not matter for this section.
+```
+
+By setting `dhcp4: no` and `dhcp6: no`, the interfaces will be brought up as part of the normal boot cycle, despite not having IP addresses assigned.
+
+Then run
+
+```shell
+sudo chmod 600 /etc/netplan/libreqos.yaml
+sudo netplan apply
+```
+
+### Option B: Netplan config for the Bifrost XDP bridge
+
+Ubuntu Server uses NetPlan, which uses .yaml files in /etc/netplan to determine interface settings.
+Here, we will add a .yaml specifically for LibreQoS - that way it is not overwritten when changes are made to the default .yaml file.
+
+```shell
+sudo nano /etc/netplan/libreqos.yaml
+```
+
+Assuming your interfaces are ens19 and ens20, here is what your file would look like:
+
+```yaml
+network:
+ ethernets:
+ ens19:
+ dhcp4: no
+ dhcp6: no
+ ens20:
+ dhcp4: no
+ dhcp6: no
+ version: 2
+```
+```{note}
+Please be sure to replace ens19 and ens20 in the example above with the correct shaping interfaces. The order of the interfaces does not matter for this section.
+```
+
+By setting `dhcp4: no` and `dhcp6: no`, the interfaces will be brought up as part of the normal boot cycle, despite not having IP addresses assigned.
+
+Then run
+
+```shell
+sudo chmod 600 /etc/netplan/libreqos.yaml
+sudo netplan apply
+```
diff --git a/_build/html/_sources/docs-es/v2.0/Quickstart/services-and-run.md.txt b/_build/html/_sources/docs-es/v2.0/Quickstart/services-and-run.md.txt
new file mode 100644
index 00000000..1e4c6864
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/Quickstart/services-and-run.md.txt
@@ -0,0 +1,70 @@
+# LibreQoS systemd services
+
+## What each service does
+### lqosd
+
+- Manages actual XDP code.
+- Coded in Rust.
+- Runs the GUI available at http://a.b.c.d:9123
+
+### lqos_scheduler
+
+- lqos_scheduler performs continuous refreshes of LibreQoS' shapers, including pulling from any enabled CRM Integrations (UISP, Splynx, Netzur).
+- Actions:
+ - On start: Run a full setup of queues
+ - Every X minutes: Update queues, pulling new configuration from CRM integration, if enabled.
+ - The default minute interval is 30, so the refresh occurs every 30 minutes by default.
+ - The minute interval is adjustable with the setting `queue_refresh_interval_mins` in `/etc/lqos.conf`.
+
+## Checking service status
+
+```
+sudo systemctl status lqosd lqos_scheduler
+```
+
+If the status of one of the two services shows 'failed', examine why using journalctl, which shows the full status of the service. For example, if lqosd failed, you would run:
+```
+sudo journalctl -u lqosd -b
+```
+Press the End key on the keyboard to take you to the bottom of the log to see the latest updates to that log.
+
+Lqosd will provide specific reasons it failed, such as an interface not being up, an interface lacking multi-queue, or other cocnerns.
+
+## Debugging lqos_scheduler
+
+In the background, lqos_scheduler runs the Python script scheduler.py, which in turn runs the Python script LibreQoS.py
+
+- scheduler.py: performs continuous refreshes of LibreQoS' shapers, including pulling from any enabled CRM Integrations (UISP, Splynx, Netzur).
+- LibreQoS.py: creates and updates queues / shaping of devices
+
+One-time runs of these individual components can be very helpful for debugging and to make sure everything is correctly configured.
+
+First, stop lqos_scheduler
+
+```shell
+sudo systemctl stop lqos_scheduler
+```
+
+For one-time runs of LibreQoS.py, use
+
+```shell
+sudo ./LibreQoS.py
+```
+
+- To use the debug mode with more verbose output, use:
+
+```shell
+sudo ./LibreQoS.py --debug
+```
+
+To confirm that lqos_scheduler (scheduler.py) is able to work correctly, run:
+
+```shell
+sudo python3 scheduler.py
+```
+
+Once you have any errors eliminated, restart lqos_scheduler with
+
+```shell
+sudo systemctl start lqos_scheduler
+```
diff --git a/_build/html/_sources/docs-es/v2.0/Quickstart/share.md.txt b/_build/html/_sources/docs-es/v2.0/Quickstart/share.md.txt
new file mode 100644
index 00000000..c1377456
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/Quickstart/share.md.txt
@@ -0,0 +1,35 @@
+# Share your before and after
+
+We ask that you please share an anonymized screenshot of your LibreQoS deployment before (monitor only mode) and after (queuing enabled) to the [LibreQoS Chat](https://chat.libreqos.io/join/fvu3cerayyaumo377xwvpev6/). This helps us gauge the impact of our software. It also makes us smile.
+
+1. Enable monitor only mode
+2. Run for 1 week
+3. Disable monitor only mode
+4. Toggle "Redact" to hide customer info in the LTS WebUI
+5. Screenshot
+
+## Enable monitor only mode
+
+```shell
+sudo nano /etc/lqos.conf
+```
+
+In the `[queues]` section, set `monitor_only = true` to switch to monitor only mode.
+
+The restart lqosd and lqos_scheduler:
+```shell
+sudo systemctl restart lqosd lqos_scheduler
+```
+
+## Disable monitor only mode
+
+```shell
+sudo nano /etc/lqos.conf
+```
+
+In the `[queues]` section, set `monitor_only = false` to switch off monitor only mode.
+
+The restart lqosd and lqos_scheduler:
+```shell
+sudo systemctl restart lqosd lqos_scheduler
+```
diff --git a/_build/html/_sources/docs-es/v2.0/TechnicalDocs/extras.md.txt b/_build/html/_sources/docs-es/v2.0/TechnicalDocs/extras.md.txt
new file mode 100644
index 00000000..abe84307
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/TechnicalDocs/extras.md.txt
@@ -0,0 +1,12 @@
+# Extras
+
+## Flamegraph
+
+```shell
+git clone https://github.com/brendangregg/FlameGraph.git
+cd FlameGraph
+sudo perf record -F 99 -a -g -- sleep 60
+perf script > out.perf
+./stackcollapse-perf.pl out.perf > out.folded
+./flamegraph.pl --title LibreQoS --width 7200 out.folded > libreqos.svg
+```
diff --git a/_build/html/_sources/docs-es/v2.0/TechnicalDocs/git-install.md.txt b/_build/html/_sources/docs-es/v2.0/TechnicalDocs/git-install.md.txt
new file mode 100644
index 00000000..0c391a53
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/TechnicalDocs/git-install.md.txt
@@ -0,0 +1,95 @@
+# Git Install (For Developers - Not Recommended)
+
+## Clone the repo
+
+The recommended install location is `/opt/libreqos`
+Go to the install location, and clone the repo:
+
+```shell
+cd /opt/
+sudo git clone https://github.com/LibreQoE/LibreQoS.git libreqos
+sudo chown -R $USER /opt/libreqos
+cd /opt/libreqos/
+git switch develop
+git pull
+```
+
+By specifying `libreqos` at the end, git will ensure the folder name is lowercase.
+
+## Install Dependencies from apt and pip
+
+You need to have a few packages from `apt` installed:
+
+```shell
+sudo apt-get install -y python3-pip clang gcc gcc-multilib llvm libelf-dev git nano graphviz curl screen llvm pkg-config linux-tools-common linux-tools-`uname -r` libbpf-dev libssl-dev
+```
+
+Then you need to install some Python dependencies:
+
+```shell
+cd /opt/libreqos
+PIP_BREAK_SYSTEM_PACKAGES=1 pip install -r requirements.txt
+sudo PIP_BREAK_SYSTEM_PACKAGES=1 pip install -r requirements.txt
+```
+
+## Install the Rust development system
+
+Run the following:
+
+```shell
+curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
+```
+
+When Rust finishes installing, it will tell you to execute a command to place the Rust build tools into your path. You need to either execute this command or logout and back in again.
+
+Once that's done, please run:
+
+```shell
+cd /opt/libreqos/src/
+./build_rust.sh
+```
+
+This will take a while the first time, but it puts everything in the right place.
+
+Now, to build rust crates, run:
+
+```shell
+cd rust
+cargo build --all
+```
+
+## Lqos.conf
+
+Copy the lqos.conf configuration file to `/etc`. This is not neccesarry if you installed using the .deb:
+
+```shell
+cd /opt/libreqos/src
+sudo cp lqos.example /etc/lqos.conf
+```
+
+## Configuration
+
+Proceed to configure settings [following this guide](../Quickstart/configuration.md).
+
+## Daemon setup
+
+## Run daemons with systemd
+
+Note: If you used the .deb installer, you can skip this section. The .deb installer automatically sets these up.
+
+You can now set up `lqosd`, and `lqos_scheduler` as systemd services.
+
+```shell
+sudo cp /opt/libreqos/src/bin/lqosd.service.example /etc/systemd/system/lqosd.service
+sudo cp /opt/libreqos/src/bin/lqos_scheduler.service.example /etc/systemd/system/lqos_scheduler.service
+```
+
+Finally, run
+
+```shell
+sudo systemctl daemon-reload
+sudo systemctl enable lqosd lqos_scheduler
+sudo systemctl start lqosd lqos_scheduler
+```
+
+You can now point a web browser at `http://a.b.c.d:9123` (replace `a.b.c.d` with the management IP address of your shaping server) and enjoy a real-time view of your network.
diff --git a/_build/html/_sources/docs-es/v2.0/TechnicalDocs/integrations.md.txt b/_build/html/_sources/docs-es/v2.0/TechnicalDocs/integrations.md.txt
new file mode 100644
index 00000000..a5e9da7b
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/TechnicalDocs/integrations.md.txt
@@ -0,0 +1,194 @@
+# Integrations
+
+## Splynx Integration
+
+First, set the relevant parameters for Splynx (splynx_api_key, splynx_api_secret, etc.) in `/etc/lqos.conf`.
+
+### Splynx API Access
+
+The Splynx Integration uses Basic authentication. For using this type of authentication, please make sure you enable [Unsecure access](https://splynx.docs.apiary.io/#introduction/authentication) in your Splynx API key settings. Also the Splynx API key should be granted access to the necessary permissions.
+
+* Tariff Plans -> Internet -> view
+* Tariff Plans -> Bundle -> view
+* Tariff Plans -> One time -> view
+* Tariff Plans -> Recurring -> view
+* FUP -> Counter -> view
+* FUP -> Compiler -> view
+* FUP -> Policies -> view
+* FUP -> Capped Data -> view
+* FUP -> CAP Tariff -> view
+* FUP -> FUP Limits -> view
+* FUP -> Traffic Usage -> view
+* Customers -> customer -> view
+* Customers -> customer information -> view
+* Customers -> Customers online -> view
+* Customers -> customer bundle services -> view
+* Customers -> customer internet services -> view
+* Customers -> traffic counter -> view
+* Customers -> customer recurring services -> view
+* Customers -> bonus traffic counter -> view
+* Customers -> CAP history -> view
+* Networking -> routers -> view
+* Networking -> network sites >view
+* Networking -> router contention -> view
+* Networking -> IPv4 networks -> view
+* Networking -> IPv4 networks IP -> view
+
+To test the Splynx Integration, use
+
+```shell
+python3 integrationSplynx.py
+```
+
+On the first successful run, it will create a ShapedDevices.csv file and network.json.
+ShapedDevices.csv will be overwritten every time the Splynx integration is run.
+
+To ensure the network.json is always overwritten with the newest version pulled in by the integration, please edit `/etc/lqos.conf` with the command `sudo nano /etc/lqos.conf`.
+Edit the file to set the value of `always_overwrite_network_json` to `true`.
+Then, run `sudo systemctl restart lqosd`.
+
+You have the option to run integrationSplynx.py automatically on boot and every X minutes (set by the parameter `queue_refresh_interval_mins`), which is highly recommended. This can be enabled by setting ```enable_splynx = true``` under the ```[splynx_integration]``` section in `/etc/lqos.conf`.
+Once set, run `sudo systemctl restart lqos_scheduler`.
+
+### Splynx Overrides
+
+You can also modify the the file `integrationSplynxBandwidths.csv` to override the default bandwidths for each Node (Site, AP).
+
+A template is available in the `/opt/libreqos/src` folder. To utilize the template, copy the file `integrationSplynxBandwidths.template.csv` (removing the `.template` part of the filename) and set the appropriate information inside each file. For example, if you want to change the set bandwidth for a site, you would do:
+```
+sudo cp /opt/libreqos/src/integrationSplynxBandwidths.template.csv /opt/libreqos/src/integrationSplynxBandwidths.csv
+```
+And edit the CSV using LibreOffice or your preferred CSV editor.
+
+## UISP Integration
+
+First, set the relevant parameters for UISP (token, url, automatic_import_uisp, etc.) in `/etc/lqos.conf`.
+```
+# Whether to run the UISP integration automatically in the lqos_scheduler service
+enable_uisp = true
+
+# Your UISP API Access Token
+token = ""
+
+# Your UISP URL (include https://, but omit anything past .com, .net, etc)
+url = "https://uisp.your_domain.com"
+
+# The site here refers to the Root site you want UISP to base its topology "perspective" from.
+# Default value is a blank string.
+site = "Site_name"
+
+# Strategy type. "full" is recommended. "flat" can be used if only client shaping is desired.
+strategy = "full"
+
+# Suspension strategy:
+# * "none" - do not handle suspensions
+# * "ignore" - do not add suspended customers to the network map
+# * "slow" - limit suspended customers to 0.1 Mbps
+suspended_strategy = "none"
+
+# UISP's reported AP capacities for AirMax can be a bit optimistic. For AirMax APs, we limit
+# to 65% of what UISP claims an AP's capacity is, by default. This is adjustable.
+airmax_capacity = 0.65
+
+# UISP's reported AP capacities for LTU are more accurate, but to be safe we adjust to 95%
+# of those capacities. This is adjustable.
+ltu_capacity = 0.95
+
+# If you want to exclude sites in UISP from appearing in your LibreQoS network.json, simply
+# include them here. For example, exclude_sites = ["Site_1", "Site_2"]
+exclude_sites = []
+
+# If you use DHCPv6, and want to pull in IPv6 CIDRs corresponding to each customer's IPv4
+# address, you can do so with this. If enabled, be sure to fill out mikrotikDHCPRouterList.csv
+# and run `python3 mikrotikFindIPv6.py` to test its functionality.
+ipv6_with_mikrotik = false
+
+# If you want customers to recieve a bit more of less than their allocated speed plan, set
+# it here. For example, 1.15 is 15% above their alloted speed plan.
+bandwidth_overhead_factor = 1.15
+
+# By default, the customer "minimum" is set to 98% of the maximuum (CIR).
+commit_bandwidth_multiplier = 0.98
+exception_cpes = []
+
+# If you have some sites branched off PtMP Access Points, set `true`
+use_ptmp_as_parent = true
+```
+
+To test the UISP Integration, use
+
+```shell
+cd /opt/libreqos/src
+sudo /opt/libreqos/src/bin/uisp_integration
+```
+
+On the first successful run, it will create a network.json and ShapedDevices.csv file.
+If a network.json file exists, it will not be overwritten, unless you set ```always_overwrite_network_json = true```.
+
+ShapedDevices.csv will be overwritten every time the UISP integration is run.
+
+To ensure the network.json is always overwritten with the newest version pulled in by the integration, please edit `/etc/lqos.conf` with the command `sudo nano /etc/lqos.conf`.
+Edit the file to set the value of `always_overwrite_network_json` to `true`.
+Then, run `sudo systemctl restart lqosd`.
+
+You have the option to run integrationUISP.py automatically on boot and every X minutes (set by the parameter `queue_refresh_interval_mins`), which is highly recommended. This can be enabled by setting ```enable_uisp = true``` in `/etc/lqos.conf`. Once set, run `sudo systemctl restart lqos_scheduler`.
+
+### UISP Overrides
+
+You can also modify the the following files to more accurately reflect your network:
+- integrationUISPbandwidths.csv
+- integrationUISProutes.csv
+
+Each of the files above have templates available in the `/opt/libreqos/src` folder. If you don't find them there, you can navigate [here](https://github.com/LibreQoE/LibreQoS/tree/develop/src). To utilize the template, copy the file (removing the `.template` part of the filename) and set the appropriate information inside each file.
+For example, if you want to change the set bandwidth for a site, you would do:
+```
+sudo cp /opt/libreqos/src/integrationUISPbandwidths.template.csv /opt/libreqos/src/integrationUISPbandwidths.csv
+```
+And edit the CSV using LibreOffice or your preferred CSV editor.
+
+#### UISP Route Overrides
+
+The default cost between nodes is 10.
+
+Say you have Site 1, Site 2, and Site 3.
+A backup path exists between Site 1 and Site 3, but is not the preferred path.
+Your preference is Site 1 > Site 2 > Site 3, but the integration by default connects Site 1 > Site 3 directly.
+
+To fix this, add a cost above the default for the path between Site 1 and Site 3.
+```
+Site 1, Site 3, 100
+```
+With this, data will flow Site 1 > Site 2 > Site 3.
+
+To make the change, perform a reload of the integration with ```sudo systemctl restart lqos_scheduler```.
+
+## Powercode Integration
+
+First, set the relevant parameters for Powercode (powercode_api_key, powercode_api_url, etc.) in `/etc/lqos.conf`.
+
+To test the Powercode Integration, use
+
+```shell
+python3 integrationPowercode.py
+```
+
+On the first successful run, it will create a ShapedDevices.csv file.
+You can modify the network.json file manually to reflect Site/AP bandwidth limits.
+ShapedDevices.csv will be overwritten every time the Powercode integration is run.
+You have the option to run integrationPowercode.py automatically on boot and every X minutes (set by the parameter `queue_refresh_interval_mins`), which is highly recommended. This can be enabled by setting ```enable_powercode = true``` in `/etc/lqos.conf`.
+
+## Sonar Integration
+
+First, set the relevant parameters for Sonar (sonar_api_key, sonar_api_url, etc.) in `/etc/lqos.conf`.
+
+To test the Sonar Integration, use
+
+```shell
+python3 integrationSonar.py
+```
+
+On the first successful run, it will create a ShapedDevices.csv file.
+If a network.json file exists, it will not be overwritten, unless you set ```always_overwrite_network_json = true```.
+You can modify the network.json file to more accurately reflect bandwidth limits.
+ShapedDevices.csv will be overwritten every time the Sonar integration is run.
+You have the option to run integrationSonar.py automatically on boot and every X minutes (set by the parameter `queue_refresh_interval_mins`), which is highly recommended. This can be enabled by setting ```enable_sonar = true``` in `/etc/lqos.conf`.
diff --git a/_build/html/_sources/docs-es/v2.0/TechnicalDocs/performance-tuning.md.txt b/_build/html/_sources/docs-es/v2.0/TechnicalDocs/performance-tuning.md.txt
new file mode 100644
index 00000000..fa959c36
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/TechnicalDocs/performance-tuning.md.txt
@@ -0,0 +1,28 @@
+# Performance Tuning
+
+## Ubuntu Starts Slowly (~2 minutes)
+
+### List all services which requires network
+
+```shell
+systemctl show -p WantedBy network-online.target
+```
+
+### For Ubuntu 22.04 this command can help
+
+```shell
+systemctl disable cloud-config iscsid cloud-final
+```
+
+### Set proper governor for CPU (baremetal/hypervisior host)
+
+```shell
+cpupower frequency-set --governor performance
+```
+
+### OSPF
+
+It is recommended to set the OSPF timers of both OSPF neighbors (core and edge router) to minimize downtime upon a reboot of the LibreQoS server.
+
+* hello interval
+* dead
diff --git a/_build/html/_sources/docs-es/v2.0/TechnicalDocs/troubleshooting.md.txt b/_build/html/_sources/docs-es/v2.0/TechnicalDocs/troubleshooting.md.txt
new file mode 100644
index 00000000..5bd88b72
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/TechnicalDocs/troubleshooting.md.txt
@@ -0,0 +1,82 @@
+# Troubleshooting
+
+## Common Issues
+
+### No WebUI at x.x.x.x:9123
+
+The WebUI is controlled by the lqosd service. Usually, when the WebUI doesn't start, it is related to lqosd being in a failed state.
+Check to see if the lqosd service is running:
+```
+sudo systemctl status lqosd
+```
+
+If the status is 'failed', examine why using journalctl, which shows the full status of the service:
+```
+journalctl -u lqosd --since "10 minutes ago"
+```
+Press the End key on the keyboard to take you to the bottom of the log to see the latest updates to that log.
+
+Lqosd will provide specific reasons it failed, such as an interface not being up, an interface lacking multi-queue, or other cocnerns.
+
+### LibreQoS Is Running, But Traffic Not Shaping
+
+In /etc/lqos.conf, ensure that `to_internet` and `to_network` are set correctly. If not, simply swap the interfaces between those and restart lqosd and the scheduler.
+
+```
+sudo systemctl restart lqosd lqos_scheduler
+```
+
+Make sure your services are running properly
+
+```
+sudo systemctl status lqosd lqos_scheduler
+```
+
+The service lqos_scheduler is dependent on the lqosd service being in a healthy, running state.
+
+### Service lqosd is not running or failed to start
+
+Check to see the state of the lqosd service:
+```
+sudo systemctl status lqosd
+```
+
+If the status is 'failed', examine why using journalctl, which shows the full status of the service:
+```
+journalctl -u lqosd --since "10 minutes ago"
+```
+Press the End key on the keyboard to take you to the bottom of the log to see the latest updates to that log.
+
+Lqosd will provide specific reasons it failed, such as an interface not being up, an interface lacking multi-queue, or other cocnerns.
+
+### Advanced lqosd debug
+
+At the command-line, run ```sudo RUST_LOG=info /opt/libreqos/src/bin/lqosd``` which runs lqosd manually, and will provide specifics regarding why it failed to start.
+
+### RTNETLINK answers: Invalid argument
+
+This tends to show up when the MQ qdisc cannot be added correctly to the NIC interface. This would suggest the NIC has insufficient RX/TX queues. Please make sure you are using the [recommended NICs](../../SystemRequirements/Compute.md#network-interface-requirements).
+
+### Python ModuleNotFoundError in Ubuntu 24.04
+```
+pip uninstall binpacking --break-system-packages --yes
+sudo pip uninstall binpacking --break-system-packages --yes
+sudo pip install binpacking --break-system-packages
+pip uninstall apscheduler --break-system-packages --yes
+sudo pip uninstall apscheduler --break-system-packages --yes
+sudo pip install apscheduler --break-system-packages
+pip uninstall deepdiff --break-system-packages --yes
+sudo pip uninstall deepdiff --break-system-packages --yes
+sudo pip install deepdiff --break-system-packages
+```
+### All customer IPs are listed under Unknown IPs, rather than Shaped Devices in GUI
+```
+cd /opt/libreqos/src
+sudo systemctl stop lqos_scheduler
+sudo python3 LibreQoS.py
+```
+
+The console output from running LibreQoS.py directly provides more specific errors regarding issues with ShapedDevices.csv and network.json
+Once you have identified the error and fixed ShapedDevices.csv and/or Network.json, please then run
+
+```sudo systemctl start lqos_scheduler```
diff --git a/_build/html/_sources/docs-es/v2.0/Updates/update.md.txt b/_build/html/_sources/docs-es/v2.0/Updates/update.md.txt
new file mode 100644
index 00000000..4788d27b
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/Updates/update.md.txt
@@ -0,0 +1,36 @@
+# Actualización a la última versión
+
+```{warning}
+Si usa el puente XDP, el tráfico dejará de pasar brevemente a través del puente cuando se reinicie lqosd (el puente XDP solo funciona mientras se ejecuta lqosd).
+```
+
+## Si instaló el .deb
+
+```
+cd ~
+sudo apt-get update
+sudo apt-get upgrade
+wget https://download.libreqos.com/{deb_url_v1_5}
+sudo apt install ./{deb_url_v1_5}
+sudo systemctl restart lqosd lqos_scheduler
+```
+
+Ahora reinicie el servidor LibreQoS con:
+```
+sudo reboot
+```
+Esto eliminará los mapas eBPF antiguos y cargará la última versión de LibreQoS..
+
+## Si lo instalaste con Git
+
+1. Cambie a su directorio `LibreQoS`(e.g. `cd /opt/LibreQoS`)
+2.Actualización desde Git: `git pull`
+3. ```git switch develop```
+5. Recompile: `./build-rust.sh`
+6. `sudo rust/remove_pinned_maps.sh`
+
+Ejecute los siguientes comandos para recargar los servicios de LibreQoS.
+
+```shell
+sudo systemctl restart lqosd lqos_scheduler
+```
diff --git a/_build/html/_sources/docs-es/v2.0/api-es.md.txt b/_build/html/_sources/docs-es/v2.0/api-es.md.txt
new file mode 100644
index 00000000..81301d1e
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/api-es.md.txt
@@ -0,0 +1,176 @@
+# API del Nodo de LibreQoS
+
+## Requisitos
+
+La API del nodo LibreQoS requiere una suscripción activa a LibreQoS Insight.
+
+## Instalación
+
+### Si instaló vía `.deb` (recomendado)
+
+`lqos_api` se instala con LibreQoS en:
+
+`/opt/libreqos/src/bin/lqos_api`
+
+### Ejecución de prueba
+
+```bash
+/opt/libreqos/src/bin/lqos_api
+```
+
+### Servicio systemd
+
+El paquete incluye un archivo de servicio de ejemplo:
+
+```bash
+sudo cp /opt/libreqos/src/bin/lqos_api.service.example /etc/systemd/system/lqos_api.service
+```
+
+Luego ejecute:
+
+```bash
+sudo systemctl daemon-reload
+sudo systemctl enable lqos_api
+sudo systemctl start lqos_api
+```
+
+### Actualizar solo el binario de la API
+
+Use el script de ayuda:
+
+```bash
+cd /opt/libreqos/src
+./update_api.sh
+```
+
+Esto descarga el `lqos_api` más reciente e instala en `/opt/libreqos/src/bin/lqos_api`.
+
+Puede omitir el reinicio del servicio:
+
+```bash
+./update_api.sh --no-restart
+```
+
+O instalar en otra ruta:
+
+```bash
+./update_api.sh --bin-dir /alguna/ruta/bin --no-restart
+```
+
+### Archivo de servicio manual (si es necesario)
+
+Si crea el servicio manualmente, use:
+
+```
+[Unit]
+After=network.service lqosd.service
+Requires=lqosd.service
+
+[Service]
+WorkingDirectory=/opt/libreqos/src/bin
+ExecStart=/opt/libreqos/src/bin/lqos_api
+Restart=always
+
+[Install]
+WantedBy=default.target
+```
+
+Luego ejecute:
+
+```bash
+sudo systemctl daemon-reload
+sudo systemctl enable lqos_api
+sudo systemctl start lqos_api
+```
+
+## Uso
+
+Vea `localhost:9122/api-docs` para la interfaz Swagger.
+
+`/api-docs` es la fuente de verdad para su versión instalada. La disponibilidad de endpoints puede cambiar entre versiones.
+
+## Guía de despliegue y hardening
+
+Postura recomendada para producción:
+
+1. Mantenga la API accesible solo desde redes de gestión confiables.
+2. No exponga la API directamente a Internet público.
+3. Si requiere acceso remoto, publíquela detrás de un reverse proxy con TLS y autenticación.
+4. Restrinja acceso entrante con allowlists de firewall (host/red).
+5. Monitoree logs de API/servicio para detectar accesos anómalos.
+
+Si la API no se necesita en un nodo, deshabilite el servicio:
+
+```bash
+sudo systemctl disable --now lqos_api
+```
+
+Si está habilitada, verifique el estado tras actualizaciones:
+
+```bash
+sudo systemctl status lqos_api
+```
+
+## Endpoints de la API
+
+### Salud y sistema
+- `/health` - Verificación de salud del servicio
+- `/reload_libreqos` - Recarga configuración de LibreQoS
+- `/validate_shaped_devices` - Valida CSV de Shaped Devices
+- `/lqos_stats` - Estadísticas internas de lqosd
+- `/stormguard_stats` - Estadísticas de StormGuard
+- `/bakery_stats` - Conteo de circuitos activos de Bakery
+
+### Métricas de tráfico
+- `/current_throughput` - Throughput actual de red
+- `/top_n_downloaders/{start}/{end}` - Top descargadores por tráfico
+- `/worst_rtt/{start}/{end}` - Hosts con peor RTT
+- `/worst_retransmits/{start}/{end}` - Hosts con más retransmisiones TCP
+- `/best_rtt/{start}/{end}` - Hosts con mejor RTT
+- `/host_counter` - Contadores de tráfico por host
+
+### Topología de red
+- `/network_map/{parent}` - Mapa de red desde nodo padre
+- `/full_network_map` - Topología completa
+- `/top_map_queues/{n}` - Top N colas por tráfico
+- `/node_names` - Nombres de nodos por ID
+- `/funnel/{target}` - Análisis de embudo hacia circuito
+
+### Gestión de circuitos
+- `/all_circuits` - Lista de todos los circuitos
+- `/raw_queue_data/{circuit_id}` - Datos de cola en bruto por circuito
+
+### Análisis de flujos
+- `/dump_active_flows` - Volcado de flujos activos (lento)
+- `/count_active_flows` - Conteo de flujos activos
+- `/top_flows/{flow_type}/{n}` - Top flujos por tipo de métrica
+- `/flows_by_ip/{ip}` - Flujos por IP específica
+- `/flow_duration` - Estadísticas de duración de flujos
+
+### Geo y protocolos
+- `/current_endpoints_by_country` - Endpoints de tráfico por país
+- `/current_endpoint_latlon` - Coordenadas geográficas de endpoints
+- `/ether_protocol_summary` - Resumen de protocolos Ethernet
+- `/ip_protocol_summary` - Resumen de protocolos IP
+
+## Cobertura de API en versiones recientes
+
+Compilaciones recientes ampliaron cobertura en algunas áreas. Dependiendo de su versión, la API también puede incluir:
+
+- Resúmenes de alertas y warnings
+- Resúmenes de conteo de dispositivos y circuitos
+- Consulta de detalle para circuito individual
+- Helpers de búsqueda para flujos de UI
+- Endpoints de detalle de scheduler y estadísticas de colas
+
+Use `localhost:9122/api-docs` para confirmar rutas y esquemas exactos en su nodo.
+
+## Capturar inventario de endpoints por release
+
+Para notas de release o runbooks internos, capture un snapshot de rutas API desde el nodo:
+
+```bash
+curl -s http://localhost:9122/api-docs | jq -r '.paths | keys[]' | sort
+```
+
+Guarde esta salida junto con artefactos del release para comparar diferencias entre versiones.
diff --git a/_build/html/_sources/docs-es/v2.0/bridge-es.md.txt b/_build/html/_sources/docs-es/v2.0/bridge-es.md.txt
new file mode 100644
index 00000000..67142374
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/bridge-es.md.txt
@@ -0,0 +1,89 @@
+# Configurar el Puente de Regulación
+
+## Elegir el Tipo de Puente
+
+Hay dos opciones para que el puente pase datos entre las dos interfaces:
+
+- Opción A: Puente Regular de Linux (Recomendado)
+- Opción B: Puente Bifrost Acelerado con XDP
+
+El puente regular de Linux es recomendado para la mayoría de las instalaciones. El puente de Linux continúa transfiriendo datos incluso si el servicio lqosd entra en un estado fallido, lo que lo hace una opción generalmente más segura para escenarios donde no hay una ruta de respaldo disponible. Funciona mejor con tarjetas de red Nvidia/Mellanox como las de la serie ConnectX-5 (que ofrecen un rendimiento superior en puentes) y configuraciones de máquinas virtuales con NICs virtualizadas. El puente Bifrost con XDP está recomendado para tarjetas de red Intel de 40G–100G que soportan XDP.
+
+A continuación, se encuentran las instrucciones para configurar Netplan, ya sea usando el puente de Linux o el puente Bifrost con XDP:
+
+## Opción A: Configuración de Netplan para un puente regular de Linux (Recomendado)
+
+Ubuntu Server utiliza Netplan, el cual se basa en archivos .yaml ubicados en /etc/netplan para determinar la configuración de interfaces.
+Aquí agregaremos un archivo .yaml específicamente para LibreQoS, de modo que no se sobrescriba cuando se hagan cambios al archivo .yaml por defecto.
+
+```shell
+sudo nano /etc/netplan/libreqos.yaml
+```
+
+Asumiendo que sus interfaces de regulación son ens19 y ens20, su archivo se vería así:
+
+```yaml
+network:
+ ethernets:
+ ens19:
+ dhcp4: no
+ dhcp6: no
+ ens20:
+ dhcp4: no
+ dhcp6: no
+ bridges:
+ br0:
+ interfaces:
+ - ens19
+ - ens20
+ version: 2
+```
+```{note}
+Asegurese de reemplazar `ens19` y `ens20` en el ejemplo anterior con las interfaces reales que utilizará para regular el tráfico. El orden de las interfaces no importa en esta sección.
+```
+
+Al establecer `dhcp4: no` y `dhcp6: no`, las interfaces de regulación se activarán como parte del ciclo normal de arranque, aunque no tengan direcciones IP asignadas.
+
+Después ejecute:
+
+```shell
+sudo chmod 600 /etc/netplan/libreqos.yaml
+sudo netplan apply
+```
+
+## Opción B: Configuración de Netplan para el puente Bifrost con XDP
+
+Ubuntu Server utiliza Netplan, el cual se basa en archivos .yaml ubicados en /etc/netplan para determinar la configuración de interfaces.
+Aquí agregaremos un archivo .yaml específicamente para LibreQoS, de modo que no se sobrescriba cuando se hagan cambios al archivo .yaml por defecto.
+
+```shell
+sudo nano /etc/netplan/libreqos.yaml
+```
+
+Asumiendo que sus interfaces de regulación son ens19 y ens20, su archivo se vería así:
+
+```yaml
+network:
+ ethernets:
+ ens19:
+ dhcp4: no
+ dhcp6: no
+ ens20:
+ dhcp4: no
+ dhcp6: no
+ version: 2
+```
+```{note}
+Asegurese de reemplazar `ens19` y `ens20` en el ejemplo anterior con las interfaces reales que utilizará para regular el tráfico. El orden de las interfaces no importa en esta sección.
+```
+
+Al establecer `dhcp4: no` y `dhcp6: no`, las interfaces de regulación se activarán como parte del ciclo normal de arranque, aunque no tengan direcciones IP asignadas.
+
+Después ejecute:
+
+```shell
+sudo chmod 600 /etc/netplan/libreqos.yaml
+sudo netplan apply
+```
+
+Para usar el puente XDP, asegurese de establecer `use_xdp_bridge` como `true` en el archivo lqos.conf dentro de la sección [Configuración](configuration-es.md).
\ No newline at end of file
diff --git a/_build/html/_sources/docs-es/v2.0/cake-es.md.txt b/_build/html/_sources/docs-es/v2.0/cake-es.md.txt
new file mode 100644
index 00000000..30b80c84
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/cake-es.md.txt
@@ -0,0 +1,54 @@
+# CAKE
+
+Por defecto, LibreQoS utiliza CAKE (Common Applications Kept Enhanced) con el parámetro diffserv4.
+
+## DSCP
+
+[https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml](https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml)
+
+### Clases de tráfico y etiquetas DSCP para Diffserv4
+
+ * Tráfico Sensible a la Latencia (CS7, CS6, EF, VA, CS5, CS4)
+ * Medios de Streaming (AF4x, AF3x, CS3, AF2x, TOS4, CS2, TOS1)
+ * Mejor Esfuerzo (CS0, AF1x, TOS2, y los no especificados)
+ * Tráfico en Segundo Plano (CS1)
+
+### Lista de puntos de código Diffserv conocidos:
+
+ * Esfuerzo Mínimo (CS1)
+ * Mejor Esfuerzo (CS0)
+ * Máxima Confiabilidad y LLT “Lo” (TOS1)
+ * Máximo Rendimiento (TOS2)
+ * Mínima Demora (TOS4)
+ * LLT "La" (TOS5)
+ * Reenvío Asegurado 1 (AF1x) - x3
+ * Reenvío Asegurado 2 (AF2x) - x3
+ * Reenvío Asegurado 3 (AF3x) - x3
+ * Reenvío Asegurado 4 (AF4x) - x3
+ * Clase de Precedencia 2 (CS2)
+ * Clase de Precedencia 3 (CS3)
+ * Clase de Precedencia 4 (CS4)
+ * Clase de Precedencia 5 (CS5)
+ * Clase de Precedencia 6 (CS6)
+ * Clase de Precedencia 7 (CS7)
+ * Admisión de Voz (VA)
+ * Reenvío Expedido (EF)
+
+### Lista de clases de tráfico según el RFC 4594:
+
+(ordenadas aproximadamente de mayor a menor prioridad en caso de congestión)
+
+(ordenadas aproximadamente de menor a mayor rendimiento en ausencia de congestión)
+
+ * Control de Red (CS6,CS7) - tráfico de enrutamiento
+ * Telefonía (EF,VA) - también conocido como VoIP
+ * Señalización (CS5) - configuración de llamadas VoIP
+ * Conferencias Multimedia (AF4x) - por ejemplo, videollamadas
+ * Interactividad en Tiempo Real (CS4) - por ejemplo, videojuegos
+ * Streaming Multimedia (AF3x) - por ejemplo, YouTube, Netflix, Twitch
+ * Difusión de Video (CS3)
+ * Datos de Baja Latencia (AF2x,TOS4) - por ejemplo, base de datos
+ * Operación, Administración y Gestión (CS2,TOS1) - por ejemplo, SSH
+ * Servicio Estándar (CS0 & puntos de código no reconocidos)
+ * Datos de Alto Rendimiento (AF1x,TOS2) - por ejemplo, navegación web
+ * Datos de Baja Prioridad (CS1) - por ejemplo, BitTorrent
\ No newline at end of file
diff --git a/_build/html/_sources/docs-es/v2.0/components-es.md.txt b/_build/html/_sources/docs-es/v2.0/components-es.md.txt
new file mode 100644
index 00000000..492ab01d
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/components-es.md.txt
@@ -0,0 +1,80 @@
+# Componentes de software de LibreQoS
+
+## Servicios systemd
+
+### lqosd
+
+- Administra la lógica de shaping/XDP.
+- Implementado en Rust.
+- Ejecuta la UI local disponible en `http://a.b.c.d:9123`.
+- Hospeda páginas de WebUI (Node Manager) como:
+ - Mapa de flujos
+ - Árbol de red
+ - Explorador ASN
+ - Árbol/Pesos de CPU
+ - Editores de configuración para integraciones (UISP, Splynx, Netzur, VISP, etc.)
+
+### lqos_scheduler
+
+- Realiza refrescos continuos de shaping, incluyendo lectura de integraciones CRM habilitadas.
+- Acciones:
+ - Al iniciar: ejecución de setup completo de colas.
+ - Cada X minutos: actualización de colas y datos de integración.
+- El intervalo por defecto es 30 minutos (`queue_refresh_interval_mins` en `/etc/lqos.conf`).
+
+### Verificación de estado
+
+```bash
+sudo systemctl status lqosd lqos_scheduler
+```
+
+Si algún servicio aparece como `failed`, revise logs:
+
+```bash
+sudo journalctl -u lqosd -b
+sudo journalctl -u lqos_scheduler -b
+```
+
+### Depuración de lqos_scheduler
+
+`lqos_scheduler` ejecuta `scheduler.py`, que a su vez invoca `LibreQoS.py`.
+
+Flujo de depuración recomendado:
+
+```bash
+sudo systemctl stop lqos_scheduler
+cd /opt/libreqos/src
+sudo ./LibreQoS.py --debug
+sudo python3 scheduler.py
+sudo systemctl start lqos_scheduler
+```
+
+## Modo privacidad en WebUI
+
+WebUI (Node Manager) incluye redacción del lado cliente para demos/capturas:
+
+- Se activa con el ícono de máscara en la barra superior.
+- La preferencia se guarda en `localStorage`.
+- Oculta datos visibles en la UI; no modifica archivos fuente.
+
+## Canal de problemas urgentes
+
+WebUI (Node Manager) incluye un canal de problemas urgentes para eventos de alta prioridad (por ejemplo, límite de circuitos mapeados).
+
+- Los eventos aparecen en el indicador de navegación superior.
+- Pueden revisarse y reconocerse desde el modal de problemas urgentes.
+- Úselo como señal rápida; confirme detalle con `journalctl -u lqosd`.
+
+## Indicador de estado del scheduler
+
+WebUI (Node Manager) incluye visibilidad del estado del scheduler.
+
+- Úselo como señal rápida de salud para jobs periódicos.
+- Si el scheduler no está saludable, valide primero estado de `lqosd` y `lqos_scheduler`.
+- Revise detalle con:
+ - `journalctl -u lqos_scheduler --since "30 minutes ago"`
+ - `journalctl -u lqosd --since "30 minutes ago"`
+
+## Solución de problemas de componentes
+
+Consulte [Solución de Problemas](troubleshooting-es.md).
diff --git a/_build/html/_sources/docs-es/v2.0/configuration-advanced-es.md.txt b/_build/html/_sources/docs-es/v2.0/configuration-advanced-es.md.txt
new file mode 100644
index 00000000..226a950c
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/configuration-advanced-es.md.txt
@@ -0,0 +1,174 @@
+# Referencia avanzada de configuración
+
+Use esta página cuando necesite configuración por CLI, edición directa de archivos o contenido de referencia detallado.
+
+## Configuración por línea de comando
+
+También puedes modificar ajustes usando la CLI.
+
+### Archivo de Configuración Principal
+### /etc/lqos.conf
+
+La configuración para cada caja reguladora de LibreQoS se almacena en el archivo `/etc/lqos.conf`.
+
+Edite el archivo para que coincida con su configuración usando:
+
+```shell
+sudo nano /etc/lqos.conf
+```
+
+En la sección ```[bridge]```, cambie `to_internet` y `to_network` para que coincidan con sus interfaces de red.
+- `to_internet = "enp1s0f1"`
+- `to_network = "enp1s0f2"`
+
+En la sección `[bridge]` del archivo lqos.conf, puede habilitar o deshabilitar el puente XDP con la opción `use_xdp_bridge`. El valor predeterminado es `false` - ya que la configuración por defecto asume un [Puente Linux](prereq-es.md). Si eligió usar el puente XDP durante la configuración de requisitos previos, establezca `use_xdp_bridge = true`.
+
+- Configure downlink_bandwidth_mbps y uplink_bandwidth_mbps para que coincidan con el ancho de banda en Mbps de la conexión WAN/Upstream de su red. Lo mismo puede hacerse para generated_pn_download_mbps y generated_pn_upload_mbps.
+- to_internet es la interfaz que apunta hacia su router de borde (edge router) y el internet.
+- to_network es la interfaz que apunta hacia su router interno (core router) (o la red interna puenteada, si su red está configurada de esa manera).
+
+Nota: Si observa que el tráfico no se está regulando cuando debería, asegúrese de invertir el orden de las interfaces y reiniciar lqosd y lqos_scheduler con: ```sudo systemctl restart lqosd lqos_scheduler```.
+
+Después de cambiar cualquier parte de `/etc/lqos.conf`, se recomienda reiniciar siempre lqosd usando: `sudo systemctl restart lqosd`. Esto integra los nuevos valores en lqos.conf, haciéndolos accesibles tanto para el código en Rust como en Python.
+
+### Netflow (opcional)
+Para habilitar Netflow, agregue la siguiente sección `[flows]` al archivo de configuración `/etc/lqos.conf`, configurando el `netflow_ip` adecuado:
+```
+[flows]
+flow_timeout_seconds = 30
+netflow_enabled = true
+netflow_port = 2055
+netflow_ip = "100.100.100.100"
+netflow_version = 5
+do_not_track_subnets = ["192.168.0.0/16"]
+```
+
+### Integraciones con CRM/NMS
+
+Más información sobre [configuración de integraciones aquí.](integrations-es.md).
+
+## Jerarquía de Red
+### Network.json
+
+Network.json permite a los operadores de internet (ISP) definir una topología de red jerárquica o plana.
+
+Si planea usar las integraciones ya incluidas en LibreQoS de UISP, Splynx o Netzur, no necesita todavía crear un archivo network.json.
+Si planea usar la integración ya incluida de UISP, el archivo network.json se creará en automático durante la primera ejecución (siempre y cuando network.json no exista previamente).
+
+Si no planea usar una integración, puede definir manualmente el archivo network.json siguiendo el archivo de plantilla - [network.example.json](https://github.com/LibreQoE/LibreQoS/blob/develop/src/network.example.json). A continuación se muestra una ilustración en tabla del network.example.json.
+
+
Entire Network
Site_1
Site_2
AP_A
Site_3
Pop_1
AP_1
PoP_5
AP_7
AP_9
PoP_6
AP_11
+
+Para redes sin nodos padre (sin puntos de acceso o sitios estrictamente definidos), edita el network.json para usar una topología de red plana con:
+```
+echo "{}" > network.json
+```
+
+#### Nodos virtuales (solo lógicos)
+
+LibreQoS soporta **nodos virtuales** en `network.json` para agrupar y para monitoreo/agregación en la WebUI/Insight. Los nodos virtuales **no** se incluyen en el árbol físico de shaping HTB (no crean clases HTB y no aplican límites de ancho de banda).
+
+Para marcar un nodo como virtual, configura `"virtual": true` en ese nodo.
+
+Ejemplo:
+
+```json
+{
+ "Region": {
+ "downloadBandwidthMbps": 1000,
+ "uploadBandwidthMbps": 1000,
+ "children": {
+ "Town": {
+ "virtual": true,
+ "downloadBandwidthMbps": 500,
+ "uploadBandwidthMbps": 500,
+ "children": {
+ "AP_A": {
+ "downloadBandwidthMbps": 200,
+ "uploadBandwidthMbps": 200
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+Notas:
+- Durante el shaping, los nodos virtuales se eliminan y sus hijos se promueven al ancestro no virtual más cercano (revisa `queuingStructure.json` para el plan físico activo).
+- `ShapedDevices.csv` aún puede usar un nodo virtual como `Parent Node` para mostrar/agrupar; LibreQoS adjuntará esos circuitos para shaping al ancestro no virtual más cercano (si el nodo virtual está en el nivel superior y no tiene ancestro no virtual, se tratará como sin nodo padre para el shaping).
+- Evita colisiones de nombres después de la promoción (dos nodos con el mismo nombre terminando al mismo nivel).
+
+#### Consideraciones de CPU
+
+
+
+#### Ayudante para convertir CSV a JSON
+
+Puede usar:
+
+```shell
+python3 csvToNetworkJSON.py
+```
+
+para convertir manualNetwork.csv en un archivo network.json.
+manualNetwork.csv puede copiarse desde el archivo de plantilla manualNetwork.template.csv.
+
+Nota: El nombre del nodo padre debe coincidir con el nombre usado para los clientes en ShapedDevices.csv.
+
+## Circuitos
+
+LibreQoS regula dispositivos individuales por sus direcciones IP, las cuales son agrupadas en "circuitos".
+
+Un circuito representa el servicio de internet de un suscriptor de la operadora de internet, el cual puede tener solo una IP asociada (por ejemplo, el router del suscriptor puede tener asignada una sola IPv4 /32) o puede tener asignado varias IPs (quizás su router tenga asignado un /29, o varias /32).
+
+El archivo ShapedDevices.csv correlaciona direcciones IP de dispositivos con circuitos (el servicio único de cada suscriptor de internet).
+
+### ShapedDevices.csv
+
+El archivo ShapedDevices.csv correlaciona las direcciones IP de los dispositivos con los circuitos (cada servicio único de suscriptor).
+
+A continuación un ejemplo de entrada en ShapedDevices.csv:
+| Circuit ID | Circuit Name | Device ID | Device Name | Parent Node | MAC | IPv4 | IPv6 | Download Min Mbps | Upload Min Mbps | Download Max Mbps | Upload Max Mbps | Comment |
+|------------|-----------------------------------------------------|-----------|-------------|-------------|-----|-------------------------|----------------------|-------------------|-----------------|-------------------|-----------------|---------|
+| 1 | 968 Circle St., Gurnee, IL 60031 | 1 | Device 1 | AP_A | | 100.64.0.1, 100.64.0.14 | fdd7:b724:0:100::/56 | 1 | 1 | 155 | 20 | |
+| 2 | 31 Marconi Street, Lake In The Hills, IL 60156 | 2 | Device 2 | AP_A | | 100.64.0.2 | fdd7:b724:0:200::/56 | 1 | 1 | 105 | 18 | |
+| 3 | 255 NW. Newport Ave., Jamestown, NY 14701 | 3 | Device 3 | AP_9 | | 100.64.0.3 | fdd7:b724:0:300::/56 | 1 | 1 | 105 | 18 | |
+| 4 | 8493 Campfire Street, Peabody, MA 01960 | 4 | Device 4 | AP_9 | | 100.64.0.4 | fdd7:b724:0:400::/56 | 1 | 1 | 105 | 18 | |
+| 2794 | 6 Littleton Drive, Ringgold, GA 30736 | 5 | Device 5 | AP_11 | | 100.64.0.5 | fdd7:b724:0:500::/56 | 1 | 1 | 105 | 18 | |
+| 2794 | 6 Littleton Drive, Ringgold, GA 30736 | 6 | Device 6 | AP_11 | | 100.64.0.6 | fdd7:b724:0:600::/56 | 1 | 1 | 105 | 18 | |
+| 5 | 93 Oklahoma Ave., Parsippany, NJ 07054 | 7 | Device 7 | AP_1 | | 100.64.0.7 | fdd7:b724:0:700::/56 | 1 | 1 | 155 | 20 | |
+| 6 | 74 Bishop Ave., Bakersfield, CA 93306 | 8 | Device 8 | AP_1 | | 100.64.0.8 | fdd7:b724:0:800::/56 | 1 | 1 | 105 | 18 | |
+| 7 | 9598 Peg Shop Drive, Lutherville Timonium, MD 21093 | 9 | Device 9 | AP_7 | | 100.64.0.9 | fdd7:b724:0:900::/56 | 1 | 1 | 105 | 18 | |
+| 8 | 115 Gartner Rd., Gettysburg, PA 17325 | 10 | Device 10 | AP_7 | | 100.64.0.10 | fdd7:b724:0:a00::/56 | 1 | 1 | 105 | 18 | |
+| 9 | 525 Birchpond St., Romulus, MI 48174 | 11 | Device 11 | Site_1 | | 100.64.0.11 | fdd7:b724:0:b00::/56 | 1 | 1 | 105 | 18 | |
+
+Si está utilizando una de nuestras integraciones con CRM, este archivo se generará automáticamente. Si no está utilizando una integración, puede editar el archivo manualmente usando la interfaz WebUI o editando directamente el archivo ShapedDevices.csv a través de la CLI.
+
+#### Múltiples IPs por Circuito
+Si necesita listar múltiples IPv4 en el campo IPv4, o múltiples IPv6 en el campo IPv6, agregue una coma entre ellas. Si está editando con un editor CSV (LibreOffice Calc, Excel), el editor CSV automáticamente colocará comillas alrededor de los elementos separados por coma. Si usted está editando el archivo manualmente con un editor de texto como notepad o nano, por favor agregue comillas alrededor de las entradas separadas por coma.
+
+```
+2794,"6 Littleton Drive, Ringgold, GA 30736",5,Device 5,AP_11,,100.64.0.5,"fdd7:b724:0:500::/56,fdd7:b724:0:600::/56",1,1,105,18,""
+```
+
+#### Edición Manual mediante WebUI
+Navegue a la interfaz Web de LibreQoS (http://a.b.c.d:9123) y seleccione Configuration > Shaped Devices.
+
+#### Edición Manual mediante CLI
+
+- Modifique el archivo ShapedDevices.csv usando su editor de hojas de cálculo preferido (LibreOffice Calc, Excel, etc.), siguiendo el archivo de plantilla - ShapedDevices.example.csv.
+- El Circuit ID es obligatorio. El Circuit ID puede ser un número o texto. Este campo NO debe incluir símbolos de hashtag (#). Cada circuito requiere un Circuit ID único – no pueden reutilizarse. Aquí, "circuito" se refiere esencialmente al servicio de un cliente. Si un cliente tiene múltiples ubicaciones en diferentes partes de su red, use un Circuit ID único para cada una.
+- Se requiere al menos una dirección IPv4 o IPv6 para cada entrada.
+- El nombre del Punto de Acceso o Sitio debe establecerse en el campo Parent Node. Puede dejarse en blanco para redes planas.
+- El archivo ShapedDevices.csv le permite establecer el ancho de banda mínimo (garantizado) y el máximo permitido por suscriptor.
+- Los valores Download Min y Upload Min de cada circuito deben ser 1 Mbps o mayores. Generalmente, deberían configurarse en 1 Mbps por defecto.
+- Los valores Download Max y Upload Max de cada circuito deben ser 2 Mbps o mayores. Generalmente, corresponden al plan de velocidad contratado por el cliente.
+- Recomendación: configure el ancho de banda mínimo en 1/1 y el máximo en 1.15X la velocidad anunciada del plan:
+ - De esta manera, cuando un AP alcance su límite, los usuarios tendrán la capacidad restante del AP distribuida equitativamente.
+ - Al establecer el máximo en 1.15X la velocidad contratada, se incrementa la probabilidad de que el suscriptor vea un resultado satisfactorio en un test de velocidad, incluso si hay tráfico ligero en segundo plano en su circuito (como un video HD, actualizaciones de software, etc.).
+ - Esto permite a los suscriptores usar hasta el limite máximo de su plan cuando el AP tiene capacidad disponible.
+
+Nota sobre SLAs: Para clientes con contratos SLA, donde garantizan un ancho de banda mínimo, puede configurar el plan contratado como el ancho de banda mínimo. De esta manera, cuando un AP se acerque a su límite, los clientes con SLA siempre tendrán esa velocidad disponible. Asegúrese de que la suma de los anchos de banda mínimos de los circuitos conectados a un nodo padre no supere la capacidad total de ese nodo padre. Si esto ocurre, LibreQoS tiene un mecanismo de seguridad que [reduce los mínimos a 1/1](https://github.com/LibreQoE/LibreQoS/pull/643) para todos los circuitos afectados.
+
+Una vez que su configuración esté completa, estará listo para ejecutar la aplicación e iniciar los [servicios systemd](./components-es.md#servicios-de-systemd)
diff --git a/_build/html/_sources/docs-es/v2.0/configuration-es.md.txt b/_build/html/_sources/docs-es/v2.0/configuration-es.md.txt
new file mode 100644
index 00000000..5bdb61ba
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/configuration-es.md.txt
@@ -0,0 +1,68 @@
+# Configurar LibreQoS
+
+## Propósito de esta página
+
+Use esta página para operaciones diarias y configuración por WebUI. Use [Referencia avanzada de configuración](configuration-advanced-es.md) para edición directa de archivos y flujos centrados en CLI.
+
+## Configuración inicial mediante la herramienta de instalación (desde el .deb)
+
+
+La herramienta de instalación configura puente, interfaces, ancho de banda, rangos IP y usuarios de WebUI.
+
+Notas:
+- La herramienta se controla con teclado (`Enter` para seleccionar, `Q` para salir sin guardar).
+- Si necesita volver a abrirla:
+ ```
+ sudo apt remove libreqos
+ sudo apt install ./{deb_url_v1_5}
+ ```
+
+### Próximos pasos
+
+Después de instalar, ingrese a la WebUI en `http://tu_ip_del_shaper:9123`.
+
+Para la mayoría de operadores:
+1. Elegir modo de operación: [Modos de operación y fuente de verdad](operating-modes-es.md)
+2. Configurar integración en WebUI: [Integraciones CRM/NMS](integrations-es.md)
+3. Validar scheduler y shaping en WebUI: [LibreQoS WebUI (Node Manager)](node-manager-ui-es.md)
+
+## Configuración mediante la interfaz web
+
+La mayoría de cambios operativos diarios se realizan en la WebUI (`http://tu_ip_del_shaper:9123/config_general.html`).
+
+### Dónde en la WebUI
+
+- Ajustes generales: `Configuration -> General`
+- Ajustes de integración: `Configuration -> Integrations`
+- Editor de dispositivos regulados: `Configuration -> Shaped Devices`
+- Validación operativa: páginas de `WebUI (Node Manager)` (dashboard/tree/flow/scheduler)
+
+## Modos de operación y fuente de verdad
+
+Lea esto primero antes de cambios en producción:
+- [Modos de operación y fuente de verdad](operating-modes-es.md)
+
+## Referencia avanzada de configuración
+
+La configuración por CLI, edición directa de archivos y referencia detallada se movió aquí:
+- [Referencia avanzada de configuración](configuration-advanced-es.md)
+
+## Configuración por línea de comando
+
+Esta sección se movió a [Referencia avanzada de configuración](configuration-advanced-es.md#configuración-por-línea-de-comando).
+
+## Jerarquía de red
+
+Esta sección se movió a [Referencia avanzada de configuración](configuration-advanced-es.md#jerarquía-de-red).
+
+## Circuitos
+
+Esta sección se movió a [Referencia avanzada de configuración](configuration-advanced-es.md#circuitos).
+
+## Páginas relacionadas
+
+- [Quickstart](quickstart-es.md)
+- [Modos de operación y fuente de verdad](operating-modes-es.md)
+- [Integraciones CRM/NMS](integrations-es.md)
+- [Referencia avanzada de configuración](configuration-advanced-es.md)
+- [Solución de problemas](troubleshooting-es.md)
diff --git a/_build/html/_sources/docs-es/v2.0/design-es.md.txt b/_build/html/_sources/docs-es/v2.0/design-es.md.txt
new file mode 100644
index 00000000..4050a790
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/design-es.md.txt
@@ -0,0 +1,30 @@
+# Escenarios de Despliegue
+
+## Despliegue inline estándar
+
+LibreQoS se coloca en línea en el borde de la red, normalmente entre el router de borde (NAT, firewall) y el router o switch de distribución principal.
+
+#### NAT/CG-NAT
+Si utilizas NAT/CG-NAT, coloca LibreQoS en línea antes del punto donde se aplica el NAT, ya que necesita regular las direcciones previas al NAT (100.64.0.0/12) y no las IP públicas posteriores.
+
+#### MPLS/VPLS
+LibreQoS puede analizar tráfico MPLS siempre que siga el patrón estándar:
+```
+(mpls tags)(optional vlan tags)(ip header)
+```
+Si tu despliegue MPLS usa un patrón distinto, lo ideal es terminar el tráfico MPLS en el router o switch de distribución principal antes de que llegue a LibreQoS.
+
+#### Enrutamiento dinámico: ruta de bypass
+- Ruta primaria (bajo costo) *a través* del servidor que ejecuta LibreQoS.
+- Ruta de respaldo (alto costo) *evitando* el servidor que ejecuta LibreQoS.
+
+#### Diagrama
+
+
+### Opción 1: Enrutamiento dinámico (recomendado)
+
+Recomendamos usar protocolos como OSPF para definir rutas de bajo y alto costo entre el router de borde y el router/switch de distribución. La ruta de bajo costo debe pasar “a través” de las interfaces puente del shaper para que LibreQoS pueda observar y regular el tráfico. Por ejemplo, la ruta OSPF de bajo costo puede tener costo 1. El enlace de alto costo (respaldo) debe omitir por completo LibreQoS y configurarse con un costo mayor (por ejemplo 100 en OSPF) para que el tráfico solo tome ese camino cuando el puente de LibreQoS no esté operativo.
+
+## Despliegue de laboratorio (opcional)
+Cuando pruebes LibreQoS por primera vez puedes desplegar un laboratorio a pequeña escala para verlo en acción.
+
diff --git a/_build/html/_sources/docs-es/v2.0/extras-es.md.txt b/_build/html/_sources/docs-es/v2.0/extras-es.md.txt
new file mode 100644
index 00000000..0f7f1d16
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/extras-es.md.txt
@@ -0,0 +1,36 @@
+# Extras
+
+## Flamegraph
+
+```shell
+git clone https://github.com/brendangregg/FlameGraph.git
+cd FlameGraph
+sudo perf record -F 99 -a -g -- sleep 60
+perf script > out.perf
+./stackcollapse-perf.pl out.perf > out.folded
+./flamegraph.pl --title LibreQoS --width 7200 out.folded > libreqos.svg
+```
+
+## Cómo habilitar CAKE o fq_codel en enlaces de respaldo (menor capacidad) en redes MikroTik
+
+Configure un Queue Tree en la interfaz del enlace punto a punto de respaldo, en el router MikroTik de cada extremo del enlace.
+
+Para enlaces inferiores a 500 Mbps en hardware razonable como un CCR2116, use CAKE:
+
+```
+/queue type
+add kind=fq-codel name=fq_codel
+add cake-diffserv=diffserv4 kind=cake name=cake
+/queue tree
+add max-limit=300M name=BACKUP_LINK_INTERFACE packet-mark=no-mark parent=BACKUP_LINK_INTERFACE queue=cake
+```
+
+Para enlaces de 500-1000 Mbps, use fq_codel:
+
+```
+/queue type
+add kind=fq-codel name=fq_codel
+add cake-diffserv=diffserv4 kind=cake name=cake
+/queue tree
+add max-limit=300M name=BACKUP_LINK_INTERFACE packet-mark=no-mark parent=BACKUP_LINK_INTERFACE queue=fq_codel
+```
diff --git a/_build/html/_sources/docs-es/v2.0/git-install-es.md.txt b/_build/html/_sources/docs-es/v2.0/git-install-es.md.txt
new file mode 100644
index 00000000..735a541e
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/git-install-es.md.txt
@@ -0,0 +1,94 @@
+# Instalación vía Git (Para desarrolladores – No recomendado)
+
+## Clonar el repositorio
+
+La ubicación recomendada para la instalación es `/opt/libreqos`
+Diríjase a dicha ubicación e inicie la clonación del repositorio:
+
+```shell
+cd /opt/
+sudo git clone https://github.com/LibreQoE/LibreQoS.git libreqos
+sudo chown -R $USER /opt/libreqos
+cd /opt/libreqos/
+git pull
+```
+
+Al especificar `libreqos` al final, Git asegurará que el nombre del directorio esté en minúsculas.
+
+## Instalar dependencias con apt y pip
+
+Es necesario instalar ciertos paquetes mediante `apt`:
+
+```shell
+sudo apt-get install -y python3-pip clang mold esbuild gcc gcc-multilib llvm libelf-dev git nano graphviz curl screen llvm pkg-config linux-tools-common linux-tools-`uname -r` libbpf-dev libssl-dev
+```
+
+Posteriormente, debe instalar algunas dependencias de Python:
+
+```shell
+cd /opt/libreqos
+PIP_BREAK_SYSTEM_PACKAGES=1 pip install -r requirements.txt
+sudo PIP_BREAK_SYSTEM_PACKAGES=1 pip install -r requirements.txt
+```
+
+## Instalar el entorno de desarrollo de Rust
+
+Ejecute el siguiente comando:
+
+```shell
+curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
+```
+
+Una vez finalizada la instalación de Rust, se le indicará que ejecute un comando para añadir las herramientas de construcción de Rust a su variable de entorno PATH. Deberá ejecutar dicho comando o bien cerrar sesión y volver a iniciarla.
+
+Después, ejecute lo siguiente:
+
+```shell
+cd /opt/libreqos/src/
+./build_rust.sh
+```
+
+Este proceso tomará algo de tiempo la primera vez, pero colocará todos los componentes en las ubicaciones correspondientes.
+
+Ahora, para compilar los crates de Rust, ejecute:
+
+```shell
+cd rust
+cargo build --all
+```
+
+## Lqos.conf
+
+Copie el archivo de configuración lqos.conf al directorio `/etc`. Este paso no es necesario si realizó la instalación utilizando el archivo .deb:
+
+```shell
+cd /opt/libreqos/src
+sudo cp lqos.example /etc/lqos.conf
+```
+
+## Configuración
+
+Proceda a configurar los parámetros [siguiendo esta guía](configuration-es.md).
+
+## Configuración de servicios (Daemons)
+
+## Ejecutar los servicios con systemd
+
+Nota: Si utilizó el instalador .deb, puede omitir esta sección. Dicho instalador configura los servicios automáticamente.
+
+Ahora puede configurar los servicios `lqosd` y `lqos_scheduler` para que se ejecuten como servicios gestionados por systemd.
+
+```shell
+sudo cp /opt/libreqos/src/bin/lqosd.service.example /etc/systemd/system/lqosd.service
+sudo cp /opt/libreqos/src/bin/lqos_scheduler.service.example /etc/systemd/system/lqos_scheduler.service
+```
+
+Finalmente, ejecute:
+
+```shell
+sudo systemctl daemon-reload
+sudo systemctl enable lqosd lqos_scheduler
+sudo systemctl start lqosd lqos_scheduler
+```
+
+Ahora puede abrir un navegador web en `http://a.b.c.d:9123` (reemplace `a.b.c.d` con la dirección IP de administración de su servidor de shaping) y disfrutar de una vista en tiempo real de su red.
diff --git a/_build/html/_sources/docs-es/v2.0/high-availability-es.md.txt b/_build/html/_sources/docs-es/v2.0/high-availability-es.md.txt
new file mode 100644
index 00000000..49ce9513
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/high-availability-es.md.txt
@@ -0,0 +1,81 @@
+# Alta Disponibilidad y Dominios de Falla
+
+Esta página describe un modelo práctico de activo/respaldo para LibreQoS.
+
+## Alcance y Supuestos
+
+- Esta página cubre alta disponibilidad de LibreQoS con un diseño activo/respaldo.
+- La conmutación por falla debe controlarse con enrutamiento dinámico (por ejemplo OSPF o BGP).
+- No se prescribe ningún fabricante de hardware o router.
+- La alta disponibilidad específica de Insight está fuera del alcance de esta página.
+
+## Modelo HA Activo/Respaldo
+
+Una ruta está activa (preferida) y otra está en respaldo (espera). La política de enrutamiento controla la selección de ruta y la conmutación por falla.
+
+## Ejemplo OSPF (Costo 1 Primario, Costo 100 Respaldo)
+
+Use el costo de interfaz OSPF para preferir la ruta activa.
+
+- Ruta primaria de LibreQoS: `ip ospf cost 1`
+- Ruta de respaldo de LibreQoS: `ip ospf cost 100`
+
+Resultado conceptual:
+
+- Estado normal: el tráfico usa la ruta primaria porque el costo `1` es menor que `100`.
+- Estado de falla: si la ruta/router primaria cae, OSPF converge y el tráfico usa la ruta de respaldo.
+- Estado de recuperación: cuando la primaria vuelve a estar sana, el tráfico regresa a la primaria por su menor costo.
+
+Intención de política:
+
+1. Mantener ambas rutas activas y enrutables todo el tiempo.
+2. Asegurar que el respaldo tenga capacidad suficiente para el pico esperado.
+3. Probar conmutación por falla y retorno en ventanas de mantenimiento.
+
+## Equivalente en BGP (Si Usa BGP en Lugar de OSPF)
+
+Si usa BGP, utilice controles de preferencia estándar para definir una ruta primaria y otra de respaldo (por ejemplo local preference, MED o AS path prepending según su diseño). Mantenga la política determinista y documentada.
+
+## Recuperación y Retorno (Runbook Conceptual)
+
+1. Confirmar si ocurrió la conmutación por falla (tabla de rutas/verificación de camino).
+2. Verificar que el tráfico de clientes esté fluyendo por la ruta de respaldo.
+3. Reparar la ruta primaria fallida.
+4. Validar la salud de la ruta primaria.
+5. Restaurar la preferencia de rutas a su estado normal (primaria preferida).
+6. Verificar que el tráfico regresó a la primaria y que el rendimiento es estable.
+
+## Mantenimiento Planificado (Procedimiento Conceptual)
+
+1. Anunciar ventana y criterios de éxito.
+2. Confirmar salud y capacidad de la ruta de respaldo.
+3. Mover tráfico al respaldo usando política de enrutamiento.
+4. Realizar mantenimiento en la ruta activa anterior.
+5. Validar la ruta reparada.
+6. Opcionalmente regresar el tráfico al estado activo normal.
+7. Cerrar la ventana con notas de validación posteriores al cambio.
+
+## Lista de Verificación de Preparación HA
+
+- El enrutamiento dinámico está implementado y documentado.
+- Las preferencias activo/respaldo son explícitas y probadas.
+- Monitoreo y alertas cubren ambas rutas y dependencias clave.
+- El runbook de guardia incluye pasos de failover y failback.
+- Existe una cadencia de pruebas regulares (por ejemplo pruebas trimestrales).
+- La capacidad de la ruta de respaldo está validada para carga pico realista.
+
+## Límites Conocidos
+
+- La alta disponibilidad depende de la calidad del diseño de red circundante.
+- La convergencia del enrutamiento dinámico no es instantánea.
+- Una política mal configurada puede causar failover asimétrico o inestable.
+- HA no reemplaza respaldos ni disciplina operativa.
+
+## Documentación Relacionada
+
+- [Planificación de Escala y Diseño de Topología](scale-topology-es.md)
+- [Ajuste de rendimiento](performance-tuning-es.md)
+- [StormGuard](stormguard-es.md)
+- [Configuración](configuration-es.md)
+- [Integraciones](integrations-es.md)
+- [Resolución de Problemas](troubleshooting-es.md)
diff --git a/_build/html/_sources/docs-es/v2.0/insight-es.md.txt b/_build/html/_sources/docs-es/v2.0/insight-es.md.txt
new file mode 100644
index 00000000..65a6d43a
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/insight-es.md.txt
@@ -0,0 +1,135 @@
+# LibreQoS Insight (Insight)
+
+## Acerca de Insight
+Conoce más sobre Insight en nuestro sitio web, [aquí](https://libreqos.io/insight/).
+
+## Interfaz de Insight
+
+### Barra de tareas
+
+
+
+Si tienes más de una caja reguladora (shaper), puedes elegir cuál visualizar desde el desplegable **Shaper Nodes** (ubicado justo debajo del cuadro de búsqueda).
+
+### Selector de tiempo
+
+
+
+Al hacer clic en el selector de tiempo (por defecto Last 24 Hours) puedes definir el rango que se mostrará, desde 15 minutos hasta 28 días. También es posible establecer periodos personalizados (Now minus X minutes) o ventanas muy específicas.
+
+### Panel (Dashboard)
+
+Puedes ver qué caja reguladora se está consultando en la parte superior izquierda, junto a “Select a destination”.
+
+El panel de LibreQoS Insight está basado en widgets y dispone de varias pestañas que se pueden editar.
+
+#### Pestaña Traffic Overview
+
+
+
+La pestaña predeterminada es **Traffic Overview**. Muestra el tráfico en vivo y los endpoints con mayor consumo, tanto por ASN como por nodo.
+
+#### Pestaña Shaper
+
+
+
+La pestaña **Shaper** muestra estadísticas de alto nivel para una caja LibreQoS determinada.
+
+- **Active Circuit Count:** número de circuitos activos detectados (basado en el tráfico del suscriptor).
+- **Throughput:** tráfico agregado del shaper.
+- **Shaper Packets:** tasa de paquetes por segundo a lo largo del tiempo.
+- **Shaper TCP Retransmits Percentage:** porcentaje de paquetes TCP retransmitidos (proxy de pérdida); idealmente debe permanecer por debajo del 1 %.
+- **Shaper CAKE Activity:** nivel de actividad de los shapers CAKE en la red.
+- **Shaper Round Trip Time:** RTT promedio del tráfico.
+- **Shaper Round Trip Time Histogram:** el mismo RTT en formato histograma.
+- **Shaper CPU Utilization:** uso máximo y promedio de CPU en el tiempo.
+- **Shaper Memory Utilization:** uso de RAM del shaper en el tiempo.
+
+#### Pestaña Children
+
+
+
+- **Shaper Child Throughput:** rendimiento de cada nodo hijo de primer nivel.
+- **Shaper Child TCP Retransmits:** ayuda a detectar nodos con pérdidas elevadas.
+- **Shaper Child Round Trip Time:** ayuda a identificar nodos con RTT anómalo.
+
+#### Heatmaps
+
+
+
+Esta vista muestra heatmaps de RTT, retransmisiones y capacidad para los nodos de primer nivel del shaper.
+
+#### Site Rankings
+
+
+
+Esta pestaña resume la salud de los sitios / AP / etc. según RTT, retransmisiones TCP y capacidad en cada dirección.
+
+### Node Map
+
+
+
+Permite identificar la topología general de la red desde la perspectiva de Insight. Al pasar el cursor por los enlaces se muestra el throughput y las retransmisiones TCP actuales de ese tramo.
+
+### Libby (Asistente IA)
+
+
+
+Libby es el asistente IA de Insight. Puede ayudarte con dudas sobre LibreQoS o Insight basándose en la documentación oficial. Libby accede a datos en vivo y de largo plazo tanto de los shapers sincronizados como de Insight. Puede responder en la mayoría de los idiomas mediante traducción automática.
+
+Si encuentras nuevos casos de uso para Libby, comparte con nosotros cómo te ayuda en el flujo de trabajo.
+
+### Site Heatmap
+
+
+
+Esta vista entrega heatmaps de RTT, retransmisiones y capacidad para cada Access Point, OLT y sitio de tu red en una sola pantalla, lo que facilita detectar puntos problemáticos rápidamente.
+
+### Tree History
+
+
+
+Se basa en la vista Tree Overview de la WebUI de LibreQoS y muestra el diagrama Sankey a lo largo del tiempo para identificar cuellos de botella que afecten el rendimiento.
+
+### Reports
+
+
+
+Insight permite generar reportes asistidos por IA sobre circuitos específicos. Estos informes usan los últimos 7 días de actividad del cliente (características por ASN, contexto de topología y contexto geográfico) e incluyen un Perfil de usuario, Hallazgos clave, Problemas críticos, Tendencias de rendimiento, una Recomendación de mejora y elementos sugeridos para revisión manual.
+
+### Alerts
+
+
+
+La sección **Alerts** entrega advertencias automáticas sobre comportamientos fuera de norma para nodos de la red (AP, OLT, sitios, etc.).
+
+## Comportamiento de licenciamiento de Insight (lado nodo)
+
+### Material de claves local y grants offline
+
+LibreQoS guarda material de claves de Insight en:
+
+`/.keys/`
+
+Las compilaciones actuales pueden cachear grants firmados localmente para que el nodo siga operando durante pérdidas temporales de conectividad con servicios de control de Insight. La validez y expiración del grant se aplica localmente.
+
+Notas operativas:
+
+- Mantenga `.keys/` persistente entre reinicios.
+- Trate `.keys/` como material sensible.
+- Si hay estado inválido de grant/clave, `lqosd` mostrará errores de licencia/grant en logs.
+
+### Límites de circuitos mapeados y estado de licencia
+
+Compilaciones recientes aplican límites de circuitos mapeados según estado de licencia.
+
+Si su nodo está sin licencia/válido, LibreQoS puede aplicar un límite predeterminado de circuitos mapeados. Cuando se excede, los logs incluyen mensajes como:
+
+- `Mapped circuit limit reached`
+- `Bakery mapped circuit cap enforced`
+
+Cuando ocurra:
+
+1. Revise estado de licencia Insight en la UI.
+2. Revise `journalctl -u lqosd` para conteos requested/allowed/dropped.
+3. Verifique si la cantidad de circuitos mapeados excede su licencia.
diff --git a/_build/html/_sources/docs-es/v2.0/integrations-es.md.txt b/_build/html/_sources/docs-es/v2.0/integrations-es.md.txt
new file mode 100644
index 00000000..15050cbc
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/integrations-es.md.txt
@@ -0,0 +1,46 @@
+# Integraciones CRM/NMS
+
+## Propósito de esta página
+
+Use esta página para elegir y configurar integraciones CRM/NMS soportadas. Use las páginas por integración para detalles específicos.
+
+La mayoría de operadores usan las integraciones incluidas. Si usa scripts propios como fuente de verdad para `network.json` y `ShapedDevices.csv`, comience por [Modos de operación y fuente de verdad](operating-modes-es.md).
+
+## Elegir ruta de integración
+
+| Ruta | Mejor para | Fuente de verdad principal |
+|---|---|---|
+| Integración incluida | La mayoría de operadores con sistemas soportados | CRM/NMS por jobs de integración de LibreQoS |
+| Fuente-de-verdad personalizada | Operadores con sincronización propia de CRM/NMS | Archivos externos generados (`network.json`, `ShapedDevices.csv`) |
+
+## Dónde en la WebUI
+
+- Comportamiento común de integración: `Configuration -> Integrations`
+- Campos por integración: `Configuration -> Integrations`
+- Validación de salud tras cambios: `WebUI -> Scheduler Status` y `WebUI -> Urgent Issues`
+- Validación de resultados/topología: `WebUI -> Network Tree Overview` y `Flow Map`
+
+## Integraciones incluidas
+
+- [Integración con Splynx](integrations-splynx-es.md)
+- [Integración con UISP](integrations-uisp-es.md)
+- [Integración con Netzur](integrations-netzur-es.md)
+- [Integración con VISP](integrations-visp-es.md)
+- [Integración con WISPGate](integrations-wispgate-es.md)
+- [Integración con Powercode](integrations-powercode-es.md)
+- [Integración con Sonar](integrations-sonar-es.md)
+
+## Comportamiento importante de sobrescritura
+
+Cuando hay integraciones habilitadas:
+- `ShapedDevices.csv` normalmente se regenera por jobs de sincronización.
+- `network.json` también puede sobrescribirse según configuración (por ejemplo `always_overwrite_network_json`).
+- Las ediciones manuales pueden sobrescribirse en el siguiente ciclo de refresco.
+
+## Páginas relacionadas
+
+- [Quickstart](quickstart-es.md)
+- [Modos de operación y fuente de verdad](operating-modes-es.md)
+- [Configurar LibreQoS](configuration-es.md)
+- [Escalado y diseño de topología](scale-topology-es.md)
+- [Solución de problemas](troubleshooting-es.md)
diff --git a/_build/html/_sources/docs-es/v2.0/integrations-netzur-es.md.txt b/_build/html/_sources/docs-es/v2.0/integrations-netzur-es.md.txt
new file mode 100644
index 00000000..0651ed73
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/integrations-netzur-es.md.txt
@@ -0,0 +1,21 @@
+# Integración con Netzur
+
+## Resumen
+
+Use esta integración cuando Netzur sea su fuente de verdad CRM/NMS.
+
+## Configuración básica
+
+1. Configure `[netzur_integration]` en `/etc/lqos.conf`.
+2. Ejecute una importación manual de prueba.
+3. Habilite sincronización por scheduler.
+
+## Notas operativas
+
+- La integración regenera `ShapedDevices.csv`.
+- `network.json` depende de su configuración de sobrescritura.
+
+## Referencia completa
+
+- [Referencia detallada de Netzur](integrations-reference-es.md#integración-con-netzur)
+- [Modos de operación y fuente de verdad](operating-modes-es.md)
diff --git a/_build/html/_sources/docs-es/v2.0/integrations-powercode-es.md.txt b/_build/html/_sources/docs-es/v2.0/integrations-powercode-es.md.txt
new file mode 100644
index 00000000..e797a556
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/integrations-powercode-es.md.txt
@@ -0,0 +1,21 @@
+# Integración con Powercode
+
+## Resumen
+
+Use esta integración cuando Powercode sea su fuente de verdad CRM/NMS.
+
+## Configuración básica
+
+1. Configure Powercode en `/etc/lqos.conf`.
+2. Ejecute una importación manual de prueba.
+3. Habilite sincronización por scheduler.
+
+## Notas operativas
+
+- `ShapedDevices.csv` se regenera en cada sincronización.
+- Revise cómo desea gestionar `network.json` en su flujo de topología.
+
+## Referencia completa
+
+- [Referencia detallada de Powercode](integrations-reference-es.md#integración-con-powercode)
+- [Modos de operación y fuente de verdad](operating-modes-es.md)
diff --git a/_build/html/_sources/docs-es/v2.0/integrations-reference-es.md.txt b/_build/html/_sources/docs-es/v2.0/integrations-reference-es.md.txt
new file mode 100644
index 00000000..a52a6b25
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/integrations-reference-es.md.txt
@@ -0,0 +1,448 @@
+# Integraciones CRM/NMS
+
+Esta página conserva la referencia detallada heredada de integraciones.
+Para el punto de entrada orientado a tareas, use [Integraciones CRM/NMS](integrations-es.md).
+
+ * [Integración con Splynx](#integración-con-splynx)
+ + [Estrategias de Topología](#estrategias-de-topología)
+ + [Promover Nodos a Raíz (Optimización de Rendimiento)](#promover-nodos-a-raíz-optimización-de-rendimiento)
+ + [Acceso API de Splynx](#acceso-api-de-splynx)
+ + [Sobrescrituras de Splynx](#sobrescrituras-de-splynx)
+ * [Integración con Netzur](#integración-con-netzur)
+ * [Integración con VISP](#integración-con-visp)
+ * [Integración con UISP](#integración-con-uisp)
+ + [Estrategias de Topología](#estrategias-de-topología-1)
+ + [Estrategias de Manejo de Suspensiones](#estrategias-de-manejo-de-suspensiones)
+ + [Burst](#burst)
+ + [Ejemplo de Configuración](#ejemplo-de-configuración)
+ + [Sobrescrituras de UISP](#sobrescrituras-de-uisp)
+ - [Sobrescrituras de Rutas UISP](#sobrescrituras-de-rutas-uisp)
+ * [Integración con WISPGate](#integración-con-wispgate)
+ * [Integración con Powercode](#integración-con-powercode)
+ * [Integración con Sonar](#integración-con-sonar)
+
+La mayoría de operadores usan este camino de integraciones incluidas.
+Si usa scripts propios como fuente de verdad para `network.json` y `ShapedDevices.csv`, comience por [Modos de operación y fuente de verdad](configuration-es.md#modos-de-operación-y-fuente-de-verdad).
+
+Comportamiento importante cuando hay integraciones habilitadas:
+- `ShapedDevices.csv` normalmente se regenera por los jobs de sincronización.
+- El comportamiento de sobrescritura de `network.json` depende de su configuración de integración (por ejemplo `always_overwrite_network_json`).
+- Las ediciones manuales pueden sobrescribirse en el próximo ciclo de refresco.
+
+## Integración con Splynx
+
+> **⚠️ Aviso de Cambio Importante**: Antes de v1.5-RC-2, la estrategia predeterminada de Splynx era `full`. A partir de v1.5-RC-2, la estrategia predeterminada es `ap_only` para un mejor rendimiento del CPU. Si requiere el comportamiento anterior, configure explícitamente `strategy = "full"` en su sección de configuración de Splynx.
+
+Primero, configure los parámetros relevantes de Splynx (splynx_api_key, splynx_api_secret, etc.) en `/etc/lqos.conf`.
+
+### Estrategias de Topología
+
+LibreQoS soporta múltiples estrategias de topología para la integración con Splynx, balanceando el rendimiento del CPU con las necesidades de jerarquía de red:
+
+| Estrategia | Descripción | Impacto CPU | Caso de Uso |
+|------------|-------------|-------------|-------------|
+| `flat` | Solo regula suscriptores, sin jerarquía | Menor | Máximo rendimiento, regulación simple de suscriptores únicamente |
+| `ap_only` | Una capa: AP → Clientes | Bajo | **Predeterminado**. Mejor balance entre rendimiento y estructura |
+| `ap_site` | Dos capas: Sitio → AP → Clientes | Medio | Agregación a nivel de sitio con complejidad moderada |
+| `full` | Mapeo completo de topología | Mayor | Representación completa de jerarquía de red |
+
+Configure la estrategia en `/etc/lqos.conf` bajo la sección `[splynx]`:
+
+```ini
+[splynx]
+# ... otras configuraciones de splynx ...
+strategy = "ap_only"
+```
+
+**Consideraciones de Rendimiento:**
+- Las estrategias `flat` y `ap_only` reducen significativamente la carga del CPU al limitar la profundidad de la red
+- Elija `ap_only` para la mayoría de implementaciones a menos que necesite agregación de tráfico a nivel de sitio
+- Use `full` solamente si requiere representación completa de la topología de red y tiene recursos CPU adecuados
+
+### Promover Nodos a Raíz (Optimización de Rendimiento)
+
+Cuando use la estrategia de topología `full`, puede encontrar cuellos de botella de rendimiento del CPU donde todo el tráfico fluye a través de un solo sitio raíz, limitando el throughput a lo que un solo núcleo de CPU puede manejar.
+
+La función **promote_to_root** soluciona esto promoviendo sitios específicos a nodos de nivel raíz, distribuyendo la regulación de tráfico entre múltiples núcleos de CPU.
+
+**Configuración:**
+1. Navegue a Integración → Común en la interfaz web
+2. En el campo "Promover Nodos a Raíz", ingrese un nombre de sitio por línea:
+```
+Sitio_Remoto_Alpha
+Sitio_Remoto_Beta
+Centro_Datos_Oeste
+```
+
+**Beneficios:**
+- Elimina el cuello de botella de CPU único para redes con sitios remotos
+- Distribuye la regulación de tráfico entre múltiples núcleos de CPU
+- Mejora el rendimiento general de la red para topologías grandes
+- Funciona tanto con integraciones de Splynx como de UISP
+
+**Cuándo Usar:**
+- Redes con múltiples sitios remotos de alta capacidad
+- Cuando use la estrategia de topología `full` y experimente limitaciones de CPU
+- Redes grandes donde el tráfico del sitio raíz excede la capacidad de un solo núcleo
+
+### Acceso API de Splynx
+
+La integración con Splynx utiliza autenticación Básica. Para usar este tipo de autenticación, asegúrese de habilitar el [Acceso No Seguro](https://splynx.docs.apiary.io/#introduction/authentication) en la configuración de su clave API de Splynx. Además, la clave API de Splynx debe tener los permisos adecuados.
+
+| Categoría | Nombre | Permiso |
+|----------------|------------------------------|------------|
+| Tariff Plans | Internet | View |
+| FUP | Compiler | View |
+| FUP | Policies | View |
+| FUP | Capped Data | View |
+| FUP | CAP Tariff | View |
+| FUP | FUP Limits | View |
+| Customers | Customer | View |
+| Customers | Customers Online | View |
+| Customers | Customer Internet services | View |
+| Networking | Routers | View |
+| Networking | Router contention | View |
+| Networking | MikroTik | View |
+| Networking | Monitoring | View |
+| Networking | Network Sites | View |
+| Networking | IPv4 Networks | View |
+| Networking | IPv4 Networks IP | View |
+| Networking | CPE | View |
+| Networking | CPE AP | View |
+| Networking | IPv6 Networks | View |
+| Networking | IPv6 Networks IP (Addresses) | View |
+| Administration | Locations | View |
+
+Para probar la integración con Splynx, use:
+
+```shell
+python3 integrationSplynx.py
+```
+
+En la primera ejecución exitosa, se crearán los archivos ShapedDevices.csv y network.json.
+ShapedDevices.csv será sobrescrito cada vez que se ejecute la integración con Splynx.
+
+Para asegurarse de que network.json siempre se sobrescriba con la versión más reciente obtenida por la integración, edite `/etc/lqos.conf` con el comando `sudo nano /etc/lqos.conf` y configure el valor `always_overwrite_network_json` a `true`.
+Luego ejecute `sudo systemctl restart lqosd`.
+
+Tiene la opción de ejecutar integrationSplynx.py automáticamente al iniciar el equipo y cada X minutos (configurado con el parámetro `queue_refresh_interval_mins`), lo cual es altamente recomendado. Esto se habilita estableciendo ```enable_splynx = true``` bajo la sección ```[splynx_integration]``` en `/etc/lqos.conf`.
+Una vez configurado, ejecute `sudo systemctl restart lqos_scheduler`.
+
+### Sobrescrituras de Splynx
+
+También puede modificar el archivo `integrationSplynxBandwidths.csv` para sobrescribir los anchos de banda predeterminados de cada Nodo (Sitio, AP).
+
+Hay una plantilla disponible en la carpeta `/opt/libreqos/src`. Para usarla, copie el archivo `integrationSplynxBandwidths.template.csv` (eliminando la parte `.template` del nombre) y edítelo con la información correspondiente. Por ejemplo, si desea cambiar el bando de ancha de un sitio, ejecutaría:
+```
+sudo cp /opt/libreqos/src/integrationSplynxBandwidths.template.csv /opt/libreqos/src/integrationSplynxBandwidths.csv
+```
+Y luego editaría el CSV con LibreOffice o el editor de CSV de su preferencia.
+
+## Integración con Netzur
+
+Los despliegues de Netzur proporcionan un endpoint REST con información de zonas y clientes protegido con token Bearer. Configure la sección `[netzur_integration]` en `/etc/lqos.conf`:
+
+```ini
+[netzur_integration]
+enable_netzur = true
+api_key = "su-token-netzur"
+api_url = "https://netzur.ejemplo.com/api/libreqos"
+timeout_secs = 60
+use_mikrotik_ipv6 = false
+```
+
+- `enable_netzur` habilita la importación automática desde `lqos_scheduler`.
+- `api_key` es el token Bearer generado dentro de Netzur.
+- `api_url` debe devolver un JSON con los arreglos `zones` (convertidos en sitios) y `customers` (convertidos en circuitos y dispositivos).
+- `timeout_secs` permite incrementar el tiempo de espera de la petición cuando el API responde lentamente (por defecto 60 segundos).
+- `use_mikrotik_ipv6` agrega prefijos IPv6 obtenidos de `mikrotikDHCPRouterList.csv`.
+
+Para una importación manual:
+
+```bash
+python3 integrationNetzur.py
+```
+
+La integración actualiza `ShapedDevices.csv` y, salvo que `always_overwrite_network_json` esté deshabilitado, también `network.json`. Ajuste la opción Integración → Común si necesita preservar un `network.json` existente entre ejecuciones de Netzur.
+
+## Integración con VISP
+
+Primero, configure los parámetros relevantes de VISP en `/etc/lqos.conf`:
+
+```ini
+[visp_integration]
+enable_visp = true
+client_id = "su-client-id"
+client_secret = "su-client-secret"
+username = "usuario-app"
+password = "password-app"
+# Opcional: si se deja vacío, se usa el primer ISP ID del token
+# isp_id = 0
+timeout_secs = 20
+# Opcional: dominio para enriquecimiento de sesiones online
+# online_users_domain = ""
+```
+
+Notas:
+
+- La importación VISP usa GraphQL y actualmente trabaja en estrategia `flat`.
+- La integración reescribe `ShapedDevices.csv` en cada ejecución.
+- `network.json` solo se sobrescribe cuando `always_overwrite_network_json = true` (en `[integration_common]`).
+- Los tokens de VISP se cachean en `/.visp_token_cache_*.json`.
+
+Importación manual:
+
+```bash
+python3 integrationVISP.py
+```
+
+Para ejecución automática con scheduler:
+
+- `[visp_integration] enable_visp = true`
+- reinicie scheduler:
+
+```bash
+sudo systemctl restart lqos_scheduler
+```
+
+## Integración con UISP
+
+Primero, configure los parámetros relevantes de UISP en `/etc/lqos.conf`.
+
+### Estrategias de Topología
+
+LibreQoS soporta múltiples estrategias de topología para la integración con UISP para equilibrar el rendimiento del CPU con las necesidades de jerarquía de red:
+
+| Estrategia | Descripción | Impacto en CPU | Caso de Uso |
+|------------|-------------|----------------|-------------|
+| `flat` | Solo regula suscriptores por velocidad del plan de servicio | Mínimo | Máximo rendimiento, regulación simple solo de suscriptores |
+| `ap_only` | Regula por plan de servicio y Punto de Acceso | Bajo | Buen equilibrio entre rendimiento y control a nivel de AP |
+| `ap_site` | Regula por plan de servicio, Punto de Acceso y Sitio | Medio | Agregación a nivel de sitio con complejidad moderada |
+| `full` | Regula toda la red incluyendo backhauls, Sitios, APs y clientes | Alto | **Recomendado para la mayoría de implementaciones**. Jerarquía completa de red con reconocimiento de backhaul |
+
+**Cómo Elegir la Estrategia Correcta:**
+- Use `full` para la mayoría de implementaciones para obtener reconocimiento completo de la topología de red incluyendo enlaces de backhaul
+- Use `ap_site` si necesita control a nivel de sitio pero no necesita regulación de backhaul
+- Use `ap_only` para mejor rendimiento cuando no se necesita agregación de sitios
+- Use `flat` solo cuando el máximo rendimiento es crítico y no necesita ninguna jerarquía
+
+**Nota de Rendimiento:** Cuando use la estrategia `full` con redes grandes, considere usar la función **promote_to_root** (vea [Promover Nodos a Raíz](#promover-nodos-a-raíz-optimización-de-rendimiento) arriba) para distribuir la carga del CPU entre múltiples núcleos.
+
+### Estrategias de Manejo de Suspensiones
+
+Configure cómo LibreQoS maneja las cuentas de clientes suspendidos:
+
+| Estrategia | Descripción | Caso de Uso |
+|------------|-------------|-------------|
+| `none` | No manejar suspensiones | Cuando el manejo de suspensiones se gestiona en otro lugar |
+| `ignore` | No agregar clientes suspendidos al mapa de red | Reduce el número de colas y mejora el rendimiento para redes con muchas cuentas suspendidas |
+| `slow` | Limitar clientes suspendidos a 0.1 Mbps | Mantiene conectividad mínima para cuentas suspendidas (por ejemplo, portales de pago) |
+
+**Cómo Elegir una Estrategia de Suspensión:**
+- Use `none` si su router de borde u otro sistema maneja las suspensiones
+- Use `ignore` para reducir la carga del sistema al no crear colas para clientes suspendidos
+- Use `slow` para mantener conectividad mínima (útil para portales de pago o mensajes de servicio)
+
+### Burst
+
+- En UISP, las velocidades de Descarga y Subida (Download/Upload Speed) se configuran en Mbps (por ejemplo, 100 Mbps).
+- En UISP, los valores de Burst de Descarga y Subida (Download/Upload Burst) se configuran en kilobytes por segundo (kB/s).
+- Conversión y conformado:
+ - burst_mbps = kB/s × 8 / 1000
+ - Download Min = Download Speed (Mbps) × commit_bandwidth_multiplier
+ - Download Max = (Download Speed (Mbps) + burst_mbps) × bandwidth_overhead_factor
+ - Upload Min/Max se calculan igual desde Upload Speed (Mbps) y Upload Burst (kB/s)
+- Ejemplo:
+ - Valores en UISP: Download Speed = 100 Mbps, Download Burst = 12,500 kB/s
+ - El burst añade 12,500 × 8 / 1000 = 100 Mbps
+ - Download Min = 100 × commit_bandwidth_multiplier
+ - Download Max = (100 + 100) × bandwidth_overhead_factor
+- Referencia rápida (burst kB/s → Mbps añadidos):
+ - 6,250 kB/s → +50 Mbps
+ - 12,500 kB/s → +100 Mbps
+ - 25,000 kB/s → +200 Mbps
+- Notas:
+ - Deje el burst vacío/nulo en UISP para desactivarlo.
+ - Si suspended_strategy está en slow, Min y Max se fijan en 0.1 Mbps.
+
+### Ejemplo de Configuración
+
+```ini
+[uisp_integration]
+# Configuración Principal
+enable_uisp = true
+token = "su-token-api-aqui"
+url = "https://uisp.su_dominio.com"
+site = "Nombre_Sitio_Raiz" # Sitio raíz para perspectiva de topología
+
+# Estrategia de Topología (ver tabla arriba)
+strategy = "full" # Recomendado para la mayoría de implementaciones
+
+# Manejo de Suspensiones (ver tabla arriba)
+suspended_strategy = "none"
+
+# Ajustes de Capacidad
+# Las capacidades de AP reportadas por UISP pueden ser optimistas
+airmax_capacity = 0.65 # Usar 65% de la capacidad reportada de AirMax
+ltu_capacity = 0.95 # Usar 95% de la capacidad reportada de LTU
+
+# Gestión de Sitios
+exclude_sites = [] # Sitios a excluir, ej: ["Sitio_Prueba", "Sitio_Lab"]
+use_ptmp_as_parent = true # Para sitios conectados a través de APs PtMP
+
+# Ajustes de Ancho de Banda
+bandwidth_overhead_factor = 1.15 # Dar a clientes 15% sobre velocidad del plan
+commit_bandwidth_multiplier = 0.98 # Establecer mínimo al 98% del máximo (CIR)
+
+# Opciones Avanzadas
+ipv6_with_mikrotik = false # Habilitar si usa DHCPv6 con MikroTik
+always_overwrite_network_json = false # Establecer true para reconstruir topología en cada ejecución
+exception_cpes = [] # Excepciones de CPE en formato ["cpe:parent"]
+squash_sites = [] # Opcional: sitios a compactar
+enable_squashing = false # Opcional: habilita lógica adicional de compactación
+do_not_squash_sites = [] # Opcional: sitios excluidos de compactación
+ignore_calculated_capacity = false # Opcional: prioriza capacidad configurada sobre la calculada
+insecure_ssl = false # Opcional: ignora validación TLS del API UISP
+```
+
+### Opciones avanzadas/operativas de UISP
+
+Las compilaciones actuales también incluyen estas opciones en los editores de configuración de WebUI (Node Manager):
+
+- `exclude_sites`: lista de sitios a excluir de la importación.
+- `exception_cpes`: sobrescrituras `cpe:parent` para asignación ambigua.
+- `squash_sites`: lista opcional de sitios a compactar en flujos `full`.
+- `enable_squashing`: habilita compactación adicional donde aplique.
+- `do_not_squash_sites`: exclusiones explícitas de compactación.
+- `use_ptmp_as_parent`: prioriza AP PtMP como padre en rutas relevantes.
+- `ignore_calculated_capacity`: usa capacidades configuradas en lugar de calculadas.
+- `insecure_ssl`: deshabilita validación de certificados TLS para UISP.
+
+Uso recomendado:
+
+1. Mantenga `insecure_ssl = false` salvo necesidad interna clara (PKI/self-signed).
+2. Use primero `exclude_sites` y `do_not_squash_sites` para cambios más seguros.
+3. Aplique `squash_sites`/`enable_squashing` de forma incremental y valide colocación de colas tras cada cambio.
+
+Para probar la integración con UISP, ejecute:
+
+```shell
+cd /opt/libreqos/src
+sudo /opt/libreqos/src/bin/uisp_integration
+```
+En la primera ejecución exitosa, se crearán los archivos network.json y ShapedDevices.csv.
+Si ya existe un archivo network.json, no será sobrescrito a menos que configure ```always_overwrite_network_json = true```.
+
+ShapedDevices.csv será sobrescrito cada vez que se ejecute la integración de UISP.
+
+Para asegurarse de que network.json siempre sea sobrescrito con la versión más reciente obtenida por la integración, edite el archivo `/etc/lqos.conf` con el comando `sudo nano /etc/lqos.conf` y configure el valor `always_overwrite_network_json` a `true`.
+Luego ejecute: `sudo systemctl restart lqosd`.
+
+Tiene la opción de ejecutar integrationUISP.py automáticamente al iniciar el equipo y cada X minutos (configurado con el parámetro `queue_refresh_interval_mins`), lo cual es altamente recomendado. Esto se habilita estableciendo ```enable_uisp = true``` en `/etc/lqos.conf`. Una vez configurado, ejecute `sudo systemctl restart lqos_scheduler`.
+
+### Sobrescrituras de UISP
+
+También puede modificar los siguientes archivos para reflejar su red con mayor precisión:
+- integrationUISPbandwidths.csv
+- integrationUISProutes.csv
+
+Cada uno de los archivos mencionados arriba tienen plantillas, las cuales están disponibles en la carpeta `/opt/libreqos/src`. Si no los encuentra, puede obtenerlos [aquí](https://github.com/LibreQoE/LibreQoS/tree/develop/src). Para utilizarlos, copie el archivo (eliminando la parte `.template` del nombre) y edítelo con la información correspondiente.
+Por ejemplo, si desea cambiar el bando de ancha de un sitio, ejecutaría:
+```
+sudo cp /opt/libreqos/src/integrationUISPbandwidths.template.csv /opt/libreqos/src/integrationUISPbandwidths.csv
+```
+Y luego editaría el CSV con LibreOffice o el editor de CSV de su preferencia.
+
+#### Sobrescrituras de Rutas UISP
+
+El costo predeterminado entre nodos suele ser 10. La integración genera un archivo de gráfico en formato dot: `/opt/libreqos/src/graph.dot` el cuál puede visualizarse con [Graphviz](https://dreampuf.github.io/GraphvizOnline/). Esto genera un mapa con los costos de todos los enlaces.
+
+
+
+Ejemplo:
+Tiene Sitio 1, Sitio 2 y Sitio 3.
+Existe un camino de respaldo entre Sitio 1 y Sitio 3, pero no es el preferido.
+El camino preferido debería ser: Sitio 1 > Sitio 2 > Sitio 3, pero la integración conecta directamente Sitio 1 > Sitio 3 por predeterminado.
+
+Para solucionar esto, agregue un costo mayor al predeterminado entre Sitio 1 y Sitio 3:
+```
+Site 1, Site 3, 100
+Site 3, Site 1, 100
+```
+De esta forma, el tráfico seguirá el camino: Sitio 1 > Sitio 2 > Sitio 3.
+
+Para aplicar el cambio, reinicie la integración ejecutando: ```sudo systemctl restart lqos_scheduler```.
+
+## Integración con WISPGate
+Primero, configure los parámetros relevantes de WISPGate en `/etc/lqos.conf`.
+Debería haber una sección como la siguiente:
+
+```
+[wispgate_integration]
+enable_wispgate = false
+wispgate_api_token = "token"
+wispgate_api_url = "https://your_wispgate_url.com"
+```
+
+Si la sección no existe, agréguela copiando el bloque anterior.
+Después, configure los valores apropiados para wispgate_api_token y wispgate_api_url, luego guarde el archivo.
+
+Para probar la integración con WISPGate, ejecute:
+
+```shell
+python3 integrationWISPGate.py
+```
+
+En la primera ejecución exitosa, se crearán los archivos network.json y ShapedDevices.csv.
+ShapedDevices.csv será sobrescrito cada vez que se ejecute la integración de WISPGate.
+
+Para asegurarse de que network.json siempre sea sobrescrito con la versión más reciente obtenida por la integración, edite el archivo `/etc/lqos.conf` con el comando `sudo nano /etc/lqos.conf` y configure el valor `always_overwrite_network_json` a `true`.
+Luego ejecute: `sudo systemctl restart lqosd`.
+
+Tiene la opción de ejecutar integrationWISPGate.py automáticamente al iniciar el equipo y cada X minutos (configurado con el parámetro `queue_refresh_interval_mins`), lo cual es altamente recomendado. Esto se habilita estableciendo ```enable_wispgate = true``` en `/etc/lqos.conf`. Una vez configurado, ejecute `sudo systemctl restart lqos_scheduler`.
+
+## Integración con Powercode
+
+Primero, configure los parámetros relevantes de Powercode (powercode_api_key, powercode_api_url, etc.) en `/etc/lqos.conf`.
+
+Para probar la integración con Powercode, ejecute:
+
+```shell
+python3 integrationPowercode.py
+```
+
+En la primera ejecución exitosa, se creará el archivo ShapedDevices.csv.
+Puede modificar el archivo network.json manualmente para reflejar los límites de ancho de banda de los Sitios/AP.
+El archivo ShapedDevices.csv se sobrescribirá cada vez que se ejecute la integración de Powercode.
+Tiene la opción de ejecutar integrationPowercode.py automáticamente al iniciar el equipo y cada X minutos (configurado con el parámetro `queue_refresh_interval_mins`), lo cual es altamente recomendado. Esto se habilita estableciendo ```enable_powercode = true``` en `/etc/lqos.conf`.
+
+## Integración con Sonar
+
+Primero, configure los parámetros relevantes de Sonar (sonar_api_key, sonar_api_url, etc.) en `/etc/lqos.conf`.
+
+Para probar la integración con Sonar, ejecute:
+
+```shell
+python3 integrationSonar.py
+```
+
+En la primera ejecución exitosa, se crearán los archivos network.json y ShapedDevices.csv.
+Si ya existe un archivo network.json, no será sobrescrito a menos que configure ```always_overwrite_network_json = true```.
+Puede modificar el archivo network.json para reflejar con mayor precisión los límites de ancho de banda.
+El archivo ShapedDevices.csv se sobrescribirá cada vez que se ejecute la integración de Sonar.
+Tiene la opción de ejecutar integrationSonar.py automáticamente al iniciar el equipo y cada X minutos (configurado con el parámetro `queue_refresh_interval_mins`), lo cual es altamente recomendado. Esto se habilita estableciendo ```enable_sonar = true``` en `/etc/lqos.conf`.
+
+## Herramientas de Terceros
+
+### Jesync UI Tool Dashboard
+Jesync UI Tool Dashboard es un panel de control moderno, basado en la web, diseñado para facilitar, agilizar y hacer más amigable la gestión de LibreQoS y de sus archivos de integración.
+
+[https://github.com/jesienazareth/jesync_dashboard](https://github.com/jesienazareth/jesync_dashboard)
+
+### Integración MikroTik PPPoE
+Este script automatiza la sincronización de los secretos PPP de MikroTik (por ejemplo, usuarios PPPoE) y los usuarios activos de hotspot con un archivo CSV compatible con LibreQoS (ShapedDevices.csv). Supervisa continuamente el router MikroTik para detectar cambios en los secretos PPP y en los usuarios activos de hotspot, como adiciones, actualizaciones o eliminaciones, y actualiza el archivo CSV en consecuencia.
+El script también calcula los límites de velocidad (descarga/carga) según el perfil PPP asignado y garantiza que el archivo CSV siempre esté actualizado.
+
+El script está diseñado para ejecutarse como un servicio en segundo plano utilizando systemd, asegurando que se inicie automáticamente al arrancar el sistema y se reinicie en caso de algún fallo.
+
+[https://github.com/Kintoyyy/MikroTik-LibreQos-Integration](https://github.com/Kintoyyy/MikroTik-LibreQos-Integration)
diff --git a/_build/html/_sources/docs-es/v2.0/integrations-sonar-es.md.txt b/_build/html/_sources/docs-es/v2.0/integrations-sonar-es.md.txt
new file mode 100644
index 00000000..4a184797
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/integrations-sonar-es.md.txt
@@ -0,0 +1,21 @@
+# Integración con Sonar
+
+## Resumen
+
+Use esta integración cuando Sonar sea su fuente de verdad CRM/NMS.
+
+## Configuración básica
+
+1. Configure Sonar en `/etc/lqos.conf`.
+2. Ejecute una importación manual de prueba.
+3. Habilite sincronización por scheduler.
+
+## Notas operativas
+
+- `ShapedDevices.csv` se regenera en cada sincronización.
+- `network.json` depende de su configuración de sobrescritura.
+
+## Referencia completa
+
+- [Referencia detallada de Sonar](integrations-reference-es.md#integración-con-sonar)
+- [Modos de operación y fuente de verdad](operating-modes-es.md)
diff --git a/_build/html/_sources/docs-es/v2.0/integrations-splynx-es.md.txt b/_build/html/_sources/docs-es/v2.0/integrations-splynx-es.md.txt
new file mode 100644
index 00000000..4685e6ad
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/integrations-splynx-es.md.txt
@@ -0,0 +1,22 @@
+# Integración con Splynx
+
+## Resumen
+
+Use esta integración cuando Splynx sea su fuente de verdad CRM/NMS.
+
+## Configuración básica
+
+1. Configure Splynx en `/etc/lqos.conf`.
+2. Seleccione estrategia de topología (`flat`, `ap_only`, `ap_site`, `full`).
+3. Habilite sincronización automática y reinicie scheduler.
+
+## Notas operativas
+
+- `ShapedDevices.csv` se regenera en cada sincronización.
+- `network.json` depende de `always_overwrite_network_json`.
+- Use WebUI para ajustes operativos diarios.
+
+## Referencia completa
+
+- [Referencia detallada de Splynx](integrations-reference-es.md#integración-con-splynx)
+- [Modos de operación y fuente de verdad](operating-modes-es.md)
diff --git a/_build/html/_sources/docs-es/v2.0/integrations-uisp-es.md.txt b/_build/html/_sources/docs-es/v2.0/integrations-uisp-es.md.txt
new file mode 100644
index 00000000..da1fc83b
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/integrations-uisp-es.md.txt
@@ -0,0 +1,22 @@
+# Integración con UISP
+
+## Resumen
+
+Use esta integración cuando UISP sea su fuente de verdad CRM/NMS.
+
+## Configuración básica
+
+1. Configure UISP en `/etc/lqos.conf`.
+2. Elija estrategia de topología y estrategia de suspensión.
+3. Habilite sincronización automática y reinicie scheduler.
+
+## Notas operativas
+
+- `ShapedDevices.csv` se regenera en cada sincronización.
+- `network.json` depende de `always_overwrite_network_json`.
+- En modo integración, trate ediciones de archivos como temporales.
+
+## Referencia completa
+
+- [Referencia detallada de UISP](integrations-reference-es.md#integración-con-uisp)
+- [Modos de operación y fuente de verdad](operating-modes-es.md)
diff --git a/_build/html/_sources/docs-es/v2.0/integrations-visp-es.md.txt b/_build/html/_sources/docs-es/v2.0/integrations-visp-es.md.txt
new file mode 100644
index 00000000..7ca23e16
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/integrations-visp-es.md.txt
@@ -0,0 +1,21 @@
+# Integración con VISP
+
+## Resumen
+
+Use esta integración cuando VISP sea su fuente de verdad CRM/NMS.
+
+## Configuración básica
+
+1. Configure credenciales `[visp_integration]` en `/etc/lqos.conf`.
+2. Ejecute una importación manual de prueba.
+3. Habilite sincronización por scheduler.
+
+## Notas operativas
+
+- `ShapedDevices.csv` se reescribe en cada ejecución.
+- `network.json` se sobrescribe solo cuando está habilitado.
+
+## Referencia completa
+
+- [Referencia detallada de VISP](integrations-reference-es.md#integración-con-visp)
+- [Modos de operación y fuente de verdad](operating-modes-es.md)
diff --git a/_build/html/_sources/docs-es/v2.0/integrations-wispgate-es.md.txt b/_build/html/_sources/docs-es/v2.0/integrations-wispgate-es.md.txt
new file mode 100644
index 00000000..34dd51cf
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/integrations-wispgate-es.md.txt
@@ -0,0 +1,21 @@
+# Integración con WISPGate
+
+## Resumen
+
+Use esta integración cuando WISPGate sea su fuente de verdad CRM/NMS.
+
+## Configuración básica
+
+1. Configure WISPGate en `/etc/lqos.conf`.
+2. Ejecute una importación manual de prueba.
+3. Habilite sincronización por scheduler.
+
+## Notas operativas
+
+- `ShapedDevices.csv` se regenera en cada sincronización.
+- `network.json` depende de su configuración de sobrescritura.
+
+## Referencia completa
+
+- [Referencia detallada de WISPGate](integrations-reference-es.md#integración-con-wispgate)
+- [Modos de operación y fuente de verdad](operating-modes-es.md)
diff --git a/_build/html/_sources/docs-es/v2.0/node-manager-ui-es.md.txt b/_build/html/_sources/docs-es/v2.0/node-manager-ui-es.md.txt
new file mode 100644
index 00000000..018433ea
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/node-manager-ui-es.md.txt
@@ -0,0 +1,72 @@
+# Interfaz WebUI (Node Manager) de LibreQoS
+
+Esta página documenta las vistas clave de la WebUI (Node Manager) y su comportamiento operativo en la interfaz local (`http://ip_del_shaper:9123`).
+
+## Vistas principales
+
+### Dashboard
+- Resumen por widgets de throughput, retransmisiones, RTT, flujos y actividad de colas.
+- El contenido puede variar según versión y funciones habilitadas.
+
+### Vista de árbol de red
+- Vista jerárquica de nodos/circuitos desde la perspectiva del shaper.
+- Útil para identificar cuellos de botella y patrones de utilización padre/hijo.
+
+### Mapa de flujos
+- Visualización geográfica de flujos según geolocalización de endpoints.
+- Requiere volumen de datos reciente suficiente.
+
+### Explorador ASN
+- Exploración por ASN (volumen, RTT/retransmisiones y detalle de flujos asociados).
+- Resultados vacíos suelen indicar poco dato reciente, no necesariamente falla.
+
+### Árbol/ponderación de CPU
+- Muestra distribución de colas/circuitos por núcleo de CPU.
+- Ayuda a validar comportamiento de binpacking y balance de carga.
+
+### Editor de Shaped Devices
+- Editor CRUD para `ShapedDevices.csv`.
+- Incluye paginación y filtros en versiones actuales.
+
+### Problemas urgentes
+- WebUI puede mostrar problemas operativos urgentes emitidos por servicios backend.
+- Ejemplos: advertencias de límites de mapeo/licencia y errores de alta prioridad.
+- Operadores pueden reconocer/limpiar eventos desde la UI.
+- Códigos comunes: `MAPPED_CIRCUIT_LIMIT` y `TC_U16_OVERFLOW` (ver [Solución de Problemas](troubleshooting-es.md#códigos-de-problemas-urgentes-y-primeras-acciones)).
+
+### Estado del scheduler
+- WebUI muestra salud/disponibilidad del scheduler.
+- Úselo para validar refrescos periódicos después de cambios de configuración/integración.
+- Si hay errores, correlacione con:
+ - `journalctl -u lqos_scheduler --since "30 minutes ago"`
+ - `journalctl -u lqosd --since "30 minutes ago"`
+
+## Modo privacidad / redacción
+
+- Se activa con el ícono de máscara en la barra superior.
+- Es redacción del lado cliente y se guarda en `localStorage` del navegador.
+- Ayuda a ocultar PII en capturas/demos.
+- No modifica `ShapedDevices.csv`, `network.json` ni datos backend.
+
+## Comportamiento de vistas vacías
+
+Las siguientes vistas pueden verse vacías cuando hay poco dato:
+- Mapa de flujos
+- Sankey del árbol de red
+- Explorador ASN
+
+Si ocurre:
+1. Confirme que `lqosd` está saludable.
+2. Espere a que se acumule tráfico/dato reciente.
+3. Recargue la página.
+4. Revise logs:
+
+```bash
+journalctl -u lqosd --since "10 minutes ago"
+```
+
+## Páginas relacionadas
+
+- [Componentes](components-es.md)
+- [Configuración](configuration-es.md)
+- [Solución de Problemas](troubleshooting-es.md)
diff --git a/_build/html/_sources/docs-es/v2.0/operating-modes-es.md.txt b/_build/html/_sources/docs-es/v2.0/operating-modes-es.md.txt
new file mode 100644
index 00000000..fea1bcec
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/operating-modes-es.md.txt
@@ -0,0 +1,39 @@
+# Modos de operación y fuente de verdad
+
+## Propósito de esta página
+
+Use esta página para elegir y aplicar su política de fuente de verdad (integraciones incluidas vs fuente personalizada) antes de cambios en producción.
+
+LibreQoS soporta dos modos de operación principales.
+
+## Integraciones incluidas (recomendado para la mayoría de operadores)
+
+En este modo, su CRM/NMS es la fuente de verdad y los jobs de integración de LibreQoS generan los insumos de shaping.
+
+Comportamiento clave:
+- `ShapedDevices.csv` se regenera en ciclos de sincronización.
+- El comportamiento de sobrescritura de `network.json` depende de la configuración de integración (por ejemplo `always_overwrite_network_json`).
+- Las ediciones manuales directas pueden sobrescribirse en el siguiente refresco del scheduler.
+
+## Fuente-de-verdad personalizada
+
+En este modo, sus propios scripts/sistemas generan `network.json` y `ShapedDevices.csv`.
+
+Comportamiento clave:
+- Su flujo externo controla la persistencia.
+- Las ediciones por WebUI son válidas para cambios operativos rápidos.
+- Los cambios permanentes deben mantenerse en su flujo externo de fuente de verdad.
+
+## Lista de verificación de modo (antes de producción)
+
+1. Elija una fuente de verdad principal.
+2. Confirme qué sistema puede escribir insumos de shaping en producción.
+3. Confirme el comportamiento de refresco del scheduler y la cadencia de sobrescritura.
+4. Documente su flujo de cambios rápidos (WebUI, editor externo, o ambos).
+5. No mantenga ediciones en competencia en varios sistemas para los mismos objetos.
+
+## Páginas relacionadas
+
+- [Configurar LibreQoS](configuration-es.md)
+- [Integraciones CRM/NMS](integrations-es.md)
+- [Referencia avanzada de configuración](configuration-advanced-es.md)
diff --git a/_build/html/_sources/docs-es/v2.0/performance-tuning-es.md.txt b/_build/html/_sources/docs-es/v2.0/performance-tuning-es.md.txt
new file mode 100644
index 00000000..8308bf02
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/performance-tuning-es.md.txt
@@ -0,0 +1,78 @@
+# Ajuste de rendimiento
+
+## Base de CPU e IRQ
+
+Configure el governor de CPU en modo rendimiento para bare metal/hipervisor:
+
+```bash
+sudo cpupower frequency-set --governor performance
+```
+
+Confirme que el conteo de colas NIC y la distribución por CPU sean razonables:
+
+```bash
+ethtool -l
+grep -E 'CPU\\(|IRQ' /proc/interrupts | head -n 50
+```
+
+Si un solo núcleo/cola está saturado y los demás están ociosos, rebalancee afinidad IRQ/colas y revise la configuración de colas en `/etc/lqos.conf`.
+
+## Presión por topología/colas
+
+Cuando modele jerarquías grandes:
+
+- Prefiera estrategias de menor profundidad (`ap_only`/`ap_site`) salvo que necesite jerarquía completa.
+- Use `promote_to_root` en topologías multi-sitio para evitar cuellos de botella de un solo núcleo.
+- Valide CPU Tree/CPU Weights en WebUI después de cambios topológicos importantes.
+
+Consulte también [Escalado y diseño de topología](scale-topology-es.md).
+
+## Frecuencia del scheduler y carga
+
+La cadencia de `lqos_scheduler` afecta carga del plano de control y velocidad de cambios.
+
+- Comience con `queue_refresh_interval_mins` conservador.
+- Reduzca intervalo solo si su integración/API y host soportan ese churn.
+- Tras cambiar intervalo, monitoree:
+ - `journalctl -u lqos_scheduler --since "30 minutes ago"`
+ - estado del scheduler en WebUI
+
+## Despliegue de StormGuard
+
+Si usa StormGuard:
+
+1. Inicie con `dry_run = true`.
+2. Observe al menos un periodo de alto tráfico.
+3. Pase a modo activo solo tras revisar estado/depuración.
+
+Vea [StormGuard](stormguard-es.md).
+
+## Arranque lento / dependencias de red
+
+Si Ubuntu arranca lento por dependencias de `network-online`, inspeccione:
+
+```bash
+systemctl show -p WantedBy network-online.target
+```
+
+En algunos entornos Ubuntu, deshabilitar servicios no usados de cloud/iSCSI puede ayudar:
+
+```bash
+sudo systemctl disable cloud-config iscsid cloud-final
+```
+
+Valide esta acción contra su entorno antes de aplicarla.
+
+## Convergencia de ruteo (OSPF)
+
+Para despliegues enrutados, ajuste timers OSPF entre core y edge para reducir ventanas de indisponibilidad en reinicios:
+
+- hello interval
+- dead interval
+
+## Páginas relacionadas de optimización y resiliencia
+
+- [Escalado y diseño de topología](scale-topology-es.md)
+- [StormGuard](stormguard-es.md)
+- [Alta Disponibilidad y Dominios de Falla](high-availability-es.md)
+- [Solución de problemas](troubleshooting-es.md)
diff --git a/_build/html/_sources/docs-es/v2.0/prereq-es.md.txt b/_build/html/_sources/docs-es/v2.0/prereq-es.md.txt
new file mode 100644
index 00000000..11013f68
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/prereq-es.md.txt
@@ -0,0 +1,33 @@
+# Requisitos previos para la configuración del servidor
+
+## Servidores e hipervisores
+
+### Desactivar Hyper-Threading
+Desactiva el Hyper-Threading en la BIOS/UEFI de tu sistema host. El Hyper-Threading también se conoce como Simultaneous Multi Threading (SMT) en sistemas AMD. Desactivarlo es muy importante para obtener un rendimiento óptimo del filtrado cpumap con XDP y, por ende, mejorar el rendimiento y la latencia.
+
+- Inicia el sistema y presiona la tecla correspondiente para entrar a la configuración de la BIOS.
+- En sistemas AMD, deberás navegar por las opciones hasta encontrar la opción llamada "SMT Control". Normalmente se encuentra en: ```Advanced -> AMD CBS -> CPU Common Options -> Thread Enablement -> SMT Control``` Una vez localizada, cambia la opción a "Disabled" o "Off".
+- En sistemas Intel, también deberás buscar la opción para desactivar el Hyper-Threading en ajustes. En servidores HP, por ejemplo, está ubicada en: ```System Configuration > BIOS/Platform Configuration (RBSU) > Processor Options > Intel (R) Hyperthreading Options```
+- Guarda los cambios y reinicia el sistema.
+
+### Desactivar SR-IOV en la BIOS
+
+SR-IOV puede desactivar XDP nativo (modo controlador) en las Funciones Físicas (PF), forzando XDP Genérico (SKB) y reduciendo el rendimiento y la estabilidad de LibreQoS. Desactive SR-IOV en la BIOS/UEFI para las tarjetas de red (NIC) utilizadas por LibreQoS. Si existen opciones por ranura/por puerto, desactívelas.
+
+## Hipervisores
+
+### Proxmox
+
+Para las máquinas virtuales Proxmox, se requiere el paso a través de la tarjeta de red (NIC) para alcanzar un rendimiento superior a 10 Gbps (XDP vs. XDP genérico).
+
+LibreQoS requiere dos o más colas RX/TX, por lo que al usar Proxmox, asegúrese de habilitar [Multicola](https://forum.proxmox.com/threads/where-is-multiqueue.146783/) para las interfaces de modelado asignadas a la máquina virtual. La multicola debe tener un valor igual al número de núcleos de vCPU asignados a la máquina virtual.
+
+### Hyper-V
+
+#### Suplantación de MAC en Hyper-V (Si está dentro de una máquina virtual)
+
+Si su sistema LibreQoS se ejecuta dentro de Hyper-V y ha conectado dos vNIC (eth1, eth2), Hyper-V bloqueará el tráfico del puente porque este genera tramas con direcciones MAC diferentes a la asignada a la vNIC. Para solucionar esto en un host Windows:
+```
+Set-VMNetworkAdapter -VMName "YourLinuxVM" -MacAddressSpoofing On
+```
+Luego, reinicie la máquina virtual.
diff --git a/_build/html/_sources/docs-es/v2.0/quickstart-es.md.txt b/_build/html/_sources/docs-es/v2.0/quickstart-es.md.txt
new file mode 100644
index 00000000..9b528cbc
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/quickstart-es.md.txt
@@ -0,0 +1,121 @@
+# Quickstart: Elija su ruta de despliegue
+
+Use esta página para elegir rápidamente la ruta correcta y ejecutar solo los pasos de esa ruta.
+
+## Base de instalación común
+
+Complete esto una vez antes de cualquier paso específico de ruta.
+
+1. Revise supuestos de despliegue y capacidad:
+ - [Escenarios de Despliegue](design-es.md)
+ - [Requisitos del Sistema](requirements-es.md)
+2. Prepare host y sistema operativo:
+ - [Configuración del Servidor - Prerrequisitos](prereq-es.md)
+ - [Instalar Ubuntu Server 24.04](ubuntu-server-es.md)
+3. Configure el modo de puente:
+ - [Configurar Puente de Regulación](bridge-es.md)
+4. Instale LibreQoS (`.deb` recomendado):
+
+```bash
+cd ~
+sudo apt-get update
+sudo apt-get upgrade
+wget https://download.libreqos.com/{deb_url_v1_5}
+sudo apt install ./{deb_url_v1_5}
+```
+
+5. Abra WebUI en `http://your_shaper_ip:9123`.
+
+## Testbed / Lab
+
+### Cuándo elegir
+
+Quiere validar comportamiento en un entorno controlado antes de producción inline.
+
+### Haga esto ahora
+
+1. Arme topología de laboratorio (LibreQoS + endpoints generadores de tráfico + simulación opcional OSPF/BGP).
+2. Elija una pista de laboratorio:
+ - **Lab con archivos manuales**: validar comportamiento de `network.json` + `ShapedDevices.csv`.
+ - **Lab con integración soportada**: validar datos importados de suscriptores/topología.
+3. Genere tráfico y valide en WebUI (Dashboard, Tree, Flow, Scheduler Status, Urgent Issues).
+4. Confirme comportamiento de shaping y estabilidad esperada.
+
+### Luego vaya aquí
+
+- [Configurar LibreQoS](configuration-es.md)
+- [Modos de operación y fuente de verdad](operating-modes-es.md)
+- [Integraciones CRM/NMS](integrations-es.md)
+- [Solución de problemas](troubleshooting-es.md)
+
+## Integración Soportada
+
+### Cuándo elegir
+
+Su CRM/NMS está soportado por integraciones incluidas de LibreQoS.
+
+### Haga esto ahora
+
+1. Configure la integración en WebUI.
+2. Ejecute sincronización inicial y valide datos importados.
+3. Coloque LibreQoS inline para tráfico piloto.
+4. Valide señales de salud en WebUI (Scheduler Status, Urgent Issues, vistas de topología/flujo).
+5. Expanda alcance del piloto tras operación estable.
+
+Nota:
+- En modo integración, `ShapedDevices.csv` normalmente se regenera por los jobs de sincronización.
+- La sobrescritura de `network.json` depende de configuración (por ejemplo `always_overwrite_network_json`).
+
+### Luego vaya aquí
+
+- [Integraciones CRM/NMS](integrations-es.md)
+- [Escalado y diseño de topología](scale-topology-es.md)
+- [Solución de problemas](troubleshooting-es.md)
+
+## Integración con Script Personalizado
+
+### Cuándo elegir
+
+Su CRM/NMS no está soportado y usted generará `network.json` + `ShapedDevices.csv` con su propio pipeline.
+
+### Haga esto ahora
+
+1. Implemente script/proceso para generar y refrescar archivos de shaping.
+2. Declare salidas del script como fuente de verdad.
+3. Coloque LibreQoS inline para tráfico piloto.
+4. Use WebUI para verificaciones operativas y ajustes rápidos.
+5. Lleve cambios permanentes de vuelta al flujo de scripts.
+
+Nota:
+- Las ediciones por WebUI son útiles para operación rápida.
+- El estado de largo plazo debe mantenerse en su flujo externo de fuente de verdad.
+
+### Luego vaya aquí
+
+- [Modos de operación y fuente de verdad](operating-modes-es.md)
+- [Referencia avanzada de configuración](configuration-advanced-es.md)
+- [Escalado y diseño de topología](scale-topology-es.md)
+- [Solución de problemas](troubleshooting-es.md)
+
+## Archivos Manuales (<100 suscriptores)
+
+### Cuándo elegir
+
+Mantiene intencionalmente `network.json` + `ShapedDevices.csv` sin sincronización CRM/NMS.
+
+Recomendado solo para redes menores a 100 suscriptores.
+
+### Haga esto ahora
+
+1. Construya y mantenga archivos de shaping directamente.
+2. Coloque LibreQoS inline para tráfico piloto.
+3. Valide shaping y estado del scheduler en WebUI.
+4. Mantenga disciplina estricta de cambios manuales.
+5. Planifique migración a integración soportada o scripts si crece escala/volumen de cambios.
+
+### Luego vaya aquí
+
+- [Referencia avanzada de configuración](configuration-advanced-es.md)
+- [Modos de operación y fuente de verdad](operating-modes-es.md)
+- [Escalado y diseño de topología](scale-topology-es.md)
+- [Solución de problemas](troubleshooting-es.md)
diff --git a/_build/html/_sources/docs-es/v2.0/requirements-es.md.txt b/_build/html/_sources/docs-es/v2.0/requirements-es.md.txt
new file mode 100644
index 00000000..f4a842af
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/requirements-es.md.txt
@@ -0,0 +1,131 @@
+# Requisitos del Sistema
+
+LibreQoS puede ejecutarse en un servidor físico dedicado (bare metal) o como una máquina virtual (VM). El sistema operativo soportado es Ubuntu Server 24.04.
+
+## Servidor Físico (Bare Metal)
+
+### CPU
+* Se requieren 2 o más núcleos de CPU.
+* Eliga una CPU con alto [rendimiento de un solo hilo](https://www.cpubenchmark.net/singleThread.html#server-thread) dentro de su presupuesto. El regulamiento es intensivo en CPU y requiere alto rendimiento en un solo hilo.
+
+El rendimiento de un solo hilo determina la capacidad máxima de un único HTB (núcleo de CPU). Esto, a su vez, afecta la capacidad máxima de cualquier nodo de nivel superior en la jerarquía de red (por ejemplo, sitios principales en su red). También impacta la velocidad máxima de plan que puede ofrecer a sus clientes dentro de márgenes seguros.
+
+| Puntaje Single-Thread | Nodo Superior Máx. | Plan de Cliente Máx |
+|:-------------------:|:------------------:|:-----------------:|
+| 1000 | 1 Gbps | 100 Mbps |
+| 1500 | 2 Gbps | 500 Mbps |
+| 2000 | 3 Gbps | 1 Gbps |
+| 3000 | 4 Gbps | 2 Gbps |
+| 4000 | 5 Gbps | 3 Gbps |
+
+A continuación se muestra una tabla de la capacidad agregada aproximada, suponiendo que una CPU tenga una puntuación de rendimiento de un [solo hilo](https://www.cpubenchmark.net/singleThread.html#server-thread) de 1000, 2000, 3000 o 4000:
+
+| Núcleos CPU | Puntaje de un solo hilo: 1000 | Puntaje de un solo hilo: 2000 | Puntaje de un solo hilo: 3000 | Puntaje de un solo hilo: 4000 |
+|:---------:|:-------------------------:|:-------------------------:|:-------------------------:|:-------------------------:|
+| 2 | 1 Gbps | 3 Gbps | 5 Gbps | 7 Gbps |
+| 4 | 3 Gbps | 5 Gbps | 9 Gbps | 13 Gbps |
+| 6 | 4 Gbps | 8 Gbps | 14 Gbps | 20 Gbps |
+| 8 | 5 Gbps | 10 Gbps | 18 Gbps | 27 Gbps |
+| 16 | 10 Gbps | 21 Gbps | 36 Gbps | 54 Gbps |
+| 32 | 21 Gbps | 42 Gbps | 72 Gbps | 108 Gbps |
+| 64 | 42 Gbps | 84 Gbps | 144 Gbps | 216 Gbps |
+| 128 | 84 Gbps | 168 Gbps | 288 Gbps | |
+
+### Hyper-threading
+
+Se recomienda [desactivar Hyper-Threading](prereq-es.md) (Simultaneous Multi-Threading) en la configuración del BIOS/UEFI, ya que puede interferir con el procesamiento de XDP.
+
+### Memory
+* RAM Recomendada:
+
+| RAM (usando CAKE) | Máx. Suscriptores |
+| ---------------- | --------------- |
+| 8 GB | 1,000 |
+| 16 GB | 2,500 |
+| 32 GB | 5,000 |
+| 64 GB | 10,000 |
+| 128 GB | 20,000 |
+
+### Espacio en Disco
+
+Se recomienda disponer de 50 GB o más de espacio en disco, tanto para servidores físicos como para implementaciones en máquinas virtuales.
+
+### Recomendaciones de Dispositivos
+#### Dispositivo de Espacio Pequeño (1G a 10G)
+
+| Rendimiento | 10 Gbps |
+|:-----------------------:|:--------------------------------------------------------------------------------------:|
+| Por Nodo / Por Núcleo | 5 Gbps |
+| Fabricante | Minisforum |
+| Modelo | [MS-01](https://store.minisforum.com/products/minisforum-ms-01?variant=46174128898293) |
+| Opción de CPU | i9-12900H |
+| Opción de RAM | 1x32GB |
+| Opción de NIC | Built-in |
+| Rango de Temperatura | 0°C ~ 40°C |
+| Rango de Temperatura | (32°F ~ 104°F) |
+| ECC | No |
+| Energía | 19V DC |
+
+##### MS-01 Notes:
+
+Al igual que con cualquier máquina que ejecute LibreQoS, asegúrese de [desactivar Hyper-Threading](prereq-es.md). Específicamente para el MS-01, considere [reemplazar la pasta térmica](https://www.youtube.com/watch?v=G70QtUAxomU) para reducir la temperatura de la CPU en aproximadamente 20 grados centígrados (Nota: esto puede anular la garantía).
+
+#### Servidores Rackmount (10G to 100G)
+
+| Rendimiento | 10 Gbps | 10 Gbps | 25 Gbps | 50 Gbps | 100 Gbps |
+|:-----------------------:|:------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------------:|
+| Por Nodo / Por Núcleo | 5 Gbps | 5 Gbps | 3 Gbps | 3 Gbps | 4 Gbps |
+| Fabricante | Supermicro | Dell | Supermicro | Supermicro | Supermicro |
+| Modelo | [SYS-511R-M](https://store.supermicro.com/us_en/mainstream-1u-sys-511r-m.html) | [PowerEdge R260](https://www.dell.com/en-us/shop/dell-poweredge-servers/new-poweredge-r260-rack-server/spd/poweredge-r260/pe_r260_tm_vi_vp_sb?configurationid=2cd33e43-57a3-4f82-aa72-9d5f45c9e24c) | [AS-1115S-FWTRT](https://store.supermicro.com/us_en/1u-amd-epyc-8004-compact-server-as-1115s-fwtrt.html) | [AS-1015SV-WTNRT](https://store.supermicro.com/us_en/1u-amd-wio-as-1015sv-wtnrt.html) | [AS -2015CS-TNR](https://store.supermicro.com/us_en/clouddc-amd-as-2015cs-tnr.html) |
+| Opción de CPU | E-2488 | E-2456 | 8534P | 8534P | 9745 |
+| Opción de RAM | 1x32GB | 1x32GB | 4x16GB | 2x64GB | 4x64GB |
+| Opción de NIC | 10-Gigabit X710-BM2 (2 x SFP+) | Intel X710-T2L (2 x 10G RJ45) | Mellanox (2 x SFP28) | Mellanox 100-Gigabit (2 x QSFP56) | MCX653106A-HDAT |
+| Rango de Temperatura | 0°C ~ 40°C | 5–40°C | 0°C ~ 40°C | 0°C ~ 40°C | 0°C ~ 40°C |
+| Rango de Temperatura | (32°F ~ 104°F) | (41–104°F) | (32°F ~ 104°F) | (32°F ~ 104°F) | (32°F ~ 104°F) |
+| ECC | Sí | Sí | Sí | Sí | Sí |
+| Energía | AC | AC | AC | AC | AC |
+
+Otra solución rentable es adquirir un servidor usado de un proveedor de confianza, como [TheServerStore](https://www.theserverstore.com/).
+Estos proveedores suelen ofrecer servidores capaces de manejar un rendimiento de 10 Gbps, por alrededor de 500 USD.
+
+#### Server Setup Prerequisites
+
+[Requisitos previos para la configuración del servidor](prereq-es.md)
+
+### Requisitos de Interfaces de Red
+* Una interfaz de red de administración completamente separada de las interfaces de regulamiento de tráfico. Usualmente esta sería la interfaz Ethernet integrada en la placa base.
+* Una Tarjeta de Red Dedicada para Dos Interfaces de Regulamiento
+
+Las Tarjetas de Red oficialmente soportadas para las dos interfaces de regulamiento se enumeran a continuación:
+
+| Controlador NIC | Velocidad de Puerto | Modelos Sugeridos | Problemas Conocidos |
+|------------------------|------------------|-----------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------|
+| Intel X520 | 10 Gbps | | Compatibilidad de módulos* |
+| Intel X710 | 10 Gbps | [X710-BM2 10G]( https://www.fs.com/products/75600.html?now_cid=4253) | Compatibilidad de módulos* |
+| Intel XXV710 | 10 / 25 Gbps | [XXV710 25G](https://www.fs.com/products/75604.html?attribute=67774&id=1709896) | Compatibilidad de módulos* |
+| Intel XL710 | 10 / 40 Gbps | [XL710-BM2 40G](https://www.fs.com/products/75604.html?attribute=67774&id=1709896 ) | Compatibilidad de módulos* |
+| Mellanox ConnectX-4 Lx | 10/25/40/50 Gbps | | No se conocen problemas. |
+| Mellanox ConnectX-6 | 10/25 Gbps | [MCX631102AN-ADAT](https://www.fs.com/products/212177.html?now_cid=4014) | No se conocen problemas. |
+| Mellanox ConnectX-6 | 100 Gbps | [MCX623106AN-CDAT 100G](https://www.fs.com/products/119646.html?now_cid=4014) | No se conocen problemas. |
+| Mellanox ConnectX-7 | 200 Gbps | [MCX755106AS-HEAT 200G](https://www.fs.com/products/242589.html?now_cid=4014) | No se conocen problemas. |
+
+(*) Intel suele bloquear por fabricante la compatibilidad de módulos SFP+. Verifique la compatibilidad del módulo antes de comprar. Mellanox no presenta este problema.
+
+**ÚNICAMENTE brindaremos soporte para sistemas que utilicen una NIC de la lista anterior**.
+Algunas otras NICs *podrían* funcionar, pero no estarán oficialmente soportadas por LibreQoS.
+Si deseas *probar* la compatibilidad de otra tarjeta, ten en cuenta estos requisitos fundamentales de NIC:
+ * La NIC debe tener múltiples filas de transmisión/recepción (TX/RX), mayores o iguales al número de núcleos de CPU. [Aquí se explica cómo verificarlo desde la terminal](https://serverfault.com/questions/772380/how-to-tell-if-nic-has-multiqueue-enabled).
+ * La NIC debe tener [soporte de controlador XDP](https://github.com/xdp-project/xdp-project/blob/master/areas/drivers/README.org) para alto rendimiento (10 Gbps o más).
+
+Si descubres que una tarjeta no listada en la tabla anterior es compatible, por favor háznoslo saber enviando un correo a support@libreqos.io.
+
+## Máquina Virtual
+LibreQoS puede ejecutarse como una máquina virtual (VM), aunque esto implica una penalización de rendimiento del 30%. Para VMs, se requiere "atravesamiento de NIC" para alcanzar un rendimiento superior a 10 Gbps (XDP vs XDP genérico).
+LibreQoS requiere 2 o más filas RX/TX, por lo que al usar una plataforma de virtualización como Proxmox, asegúrese de habilitar [Multiqueue](https://forum.proxmox.com/threads/where-is-multiqueue.146783/) para las interfaces de regulamiento asignadas a la VM. El valor de "Multiqueue" debe ser igual al número de núcleos vCPU asignados a la VM.
+
+| Rendimiento | vCPU* | RAM | Disco |
+|:-------:|:-----:|:-----:|:-----:|
+| 1 Gbps | 2 | 8 GB | 50 GB |
+| 10 Gbps | 8 | 32 GB | 50 GB |
+
+* Se asume un rendimiento de vCPU igual al de un único núcleo del Intel Xeon E-2456 con "hyper-threading" deshabilitado.
diff --git a/_build/html/_sources/docs-es/v2.0/scale-topology-es.md.txt b/_build/html/_sources/docs-es/v2.0/scale-topology-es.md.txt
new file mode 100644
index 00000000..1d02c3bf
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/scale-topology-es.md.txt
@@ -0,0 +1,75 @@
+# Escalado y diseño de topología
+
+Esta guía se centra en diseñar `network.json` y elegir estrategias de integración para mantener rendimiento estable a escala.
+
+## Principios de diseño
+
+- Mantenga la jerarquía tan simple como sea posible.
+- Evite concentrar demasiado tráfico bajo un único padre de nivel superior.
+- Use nombres y relaciones padre/hijo estables para reducir churn de colas.
+- Valide cambios de topología en ventana de mantenimiento.
+
+## Selección de estrategia por escala
+
+Use la estrategia más simple que cumpla el objetivo operativo:
+
+| Estrategia | Ajuste típico de escala | Tradeoff |
+|---|---|---|
+| `flat` | Máximo rendimiento, mínima jerarquía | Menor visibilidad/agregación |
+| `ap_only` | Redes grandes centradas en APs | Buen rendimiento, visibilidad media |
+| `ap_site` | Redes medianas/grandes con sitio+AP | Mejor agregación, costo moderado |
+| `full` | Necesidad de ruta/backhaul completo | Mayor control y mayor costo CPU/memoria |
+
+Si necesita `full` y detecta saturación de un solo núcleo, use `promote_to_root`.
+
+## Distribución padre/hijo
+
+Objetivos:
+
+- Balancear padres de nivel superior en tráfico y cantidad de circuitos.
+- Evitar ramas excesivamente profundas sin valor real para shaping.
+- Mantener nombres de hermanos únicos y estables.
+
+Señales de alerta:
+
+- Un núcleo saturado de forma persistente y el resto ocioso.
+- Reconstrucciones grandes de colas por cambios menores.
+- CPU Tree de WebUI con distribución muy sesgada.
+
+## Nodos virtuales y agrupación lógica
+
+Los nodos virtuales ayudan para organización y agregación visual.
+
+- Úselos para mejorar operabilidad y reportes.
+- No los use para ocultar una topología física confusa.
+- Valide colisiones de nombres tras promoción virtual.
+
+## Guardrails de colas/clasificadores
+
+A gran escala, la presión sobre identificadores de clase puede ser real.
+
+- Monitoree eventos urgentes como `TC_U16_OVERFLOW`.
+- Si aparece, reduzca complejidad topológica y/o aumente paralelismo de colas.
+- Reevalúe profundidad de estrategia (`full` -> `ap_site`/`ap_only`) cuando haya riesgo.
+
+Consulte [Solución de Problemas](troubleshooting-es.md#códigos-de-problemas-urgentes-y-primeras-acciones).
+
+## Checklist de despliegue para cambios de topología
+
+1. Respaldar `network.json` y `ShapedDevices.csv`.
+2. Aplicar un conjunto de cambios por vez.
+3. Revisar logs de `lqos_scheduler` y `lqosd` tras cada cambio.
+4. Validar en WebUI:
+ - CPU Tree / CPU Weights
+ - comportamiento de mapa de flujos/ASN/árbol
+ - estado del scheduler y problemas urgentes
+5. Mantener plan de rollback con configuración y archivos previos.
+
+## Páginas relacionadas
+
+- [Integraciones](integrations-es.md)
+- [Ajuste de rendimiento](performance-tuning-es.md)
+- [StormGuard](stormguard-es.md)
+- [Alta Disponibilidad y Dominios de Falla](high-availability-es.md)
+- [Configuración](configuration-es.md)
+- [Solución de Problemas](troubleshooting-es.md)
diff --git a/_build/html/_sources/docs-es/v2.0/share-es.md.txt b/_build/html/_sources/docs-es/v2.0/share-es.md.txt
new file mode 100644
index 00000000..df427400
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/share-es.md.txt
@@ -0,0 +1,37 @@
+# Comparte tu antes y después
+
+Te pedimos que compartas una captura anonimizada de tu despliegue de LibreQoS antes (modo monitor) y después (colas activadas) en el [LibreQoS Chat](https://chat.libreqos.io/join/fvu3cerayyaumo377xwvpev6/). Esto nos ayuda a medir el impacto del software y, de paso, nos saca una sonrisa.
+
+1. Activa el modo monitor only.
+2. Déjalo ejecutándose durante 1 semana.
+3. Desactiva el modo monitor only.
+4. Activa la opción **Redact** en la WebUI de LTS para ocultar datos sensibles.
+5. Toma la captura.
+
+## Activar el modo monitor only
+
+```shell
+sudo nano /etc/lqos.conf
+```
+
+En la sección `[queues]`, establece `monitor_only = true` para pasar al modo monitor.
+
+Después reinicia lqosd y lqos_scheduler:
+
+```shell
+sudo systemctl restart lqosd lqos_scheduler
+```
+
+## Desactivar el modo monitor only
+
+```shell
+sudo nano /etc/lqos.conf
+```
+
+En la sección `[queues]`, establece `monitor_only = false` para salir del modo monitor.
+
+Después reinicia lqosd y lqos_scheduler:
+
+```shell
+sudo systemctl restart lqosd lqos_scheduler
+```
diff --git a/_build/html/_sources/docs-es/v2.0/stormguard-es.md.txt b/_build/html/_sources/docs-es/v2.0/stormguard-es.md.txt
new file mode 100644
index 00000000..d3189d1f
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/stormguard-es.md.txt
@@ -0,0 +1,81 @@
+# StormGuard
+
+StormGuard es el subsistema de ajuste adaptativo de colas de LibreQoS para eventos de congestión y calidad.
+
+> **Advertencia importante de alcance**
+> StormGuard está pensado para casos de uso específicos, como controlar congestión en enlaces WAN de ancho de banda variable (por ejemplo redes marítimas), o para un número pequeño de puntos de acceso con capacidades muy variables.
+> No está pensado para gestionar decenas o cientos de nodos al mismo tiempo.
+
+## Qué hace StormGuard
+
+- Monitorea señales en tiempo real (throughput, métricas RTT/pérdida y contexto de saturación).
+- Aplica ajustes acotados a límites de nodos configurados para proteger calidad bajo estrés.
+- Expone estado y depuración en WebUI.
+
+## Configuración
+
+StormGuard se configura en `/etc/lqos.conf` bajo `[stormguard]`.
+
+Claves comunes:
+
+- `enabled`: habilita o deshabilita StormGuard.
+- `dry_run`: calcula decisiones sin aplicar cambios de colas en vivo.
+- `targets`: lista de nodos de nivel superior a gestionar.
+- `minimum_download_percentage`: piso mínimo de descarga.
+- `minimum_upload_percentage`: piso mínimo de subida.
+- `log_file`: ruta opcional para telemetría CSV de decisiones/cambios.
+
+Ejemplo:
+
+```toml
+[stormguard]
+enabled = true
+dry_run = true
+log_file = "/var/log/stormguard.csv"
+targets = ["SITE_A", "SITE_B"]
+minimum_download_percentage = 0.5
+minimum_upload_percentage = 0.5
+```
+
+Si está probando, comience con `dry_run = true`.
+
+## UI y depuración
+
+- WebUI (Node Manager) incluye vistas de estado y depuración de StormGuard.
+- La página de depuración muestra:
+ - límites efectivos actuales
+ - métricas de evaluación
+ - contexto de reglas/decisiones
+
+## Patrón de despliegue seguro
+
+1. Habilitar con `dry_run = true`.
+2. Observar durante varios periodos pico.
+3. Validar que no haya oscilaciones indeseadas.
+4. Cambiar a `dry_run = false`.
+5. Monitorear después de cada cambio grande de topología/integración.
+
+## Solución de problemas
+
+Si el comportamiento parece incorrecto:
+
+```bash
+sudo systemctl status lqosd lqos_scheduler
+journalctl -u lqosd --since "30 minutes ago"
+```
+
+También verifique:
+
+- que los nombres en `targets` aún coincidan con `network.json`
+- que cambios de integración no hayan renombrado nodos clave
+- que los pisos mínimos sean razonables para su perfil de tráfico
+- que `log_file` (si se usa) sea escribible por el servicio
+
+## Páginas relacionadas
+
+- [Configuración](configuration-es.md)
+- [Escalado y diseño de topología](scale-topology-es.md)
+- [Ajuste de rendimiento](performance-tuning-es.md)
+- [Alta Disponibilidad y Dominios de Falla](high-availability-es.md)
+- [Componentes](components-es.md)
+- [Solución de Problemas](troubleshooting-es.md)
diff --git a/_build/html/_sources/docs-es/v2.0/troubleshooting-es.md.txt b/_build/html/_sources/docs-es/v2.0/troubleshooting-es.md.txt
new file mode 100644
index 00000000..718cc8bc
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/troubleshooting-es.md.txt
@@ -0,0 +1,226 @@
+# Solución de problemas
+
+## Empiece aquí: triage por síntoma
+
+Use esta tabla para ir al primer check rápidamente.
+
+| Síntoma | Primer check | Ubicación en WebUI | Siguiente sección |
+|---|---|---|---|
+| No se puede acceder a la WebUI | `systemctl status lqosd` | N/A (UI no disponible) | No hay WebUI en x.x.x.x:9123 |
+| Hay tráfico pero no hace shaping | verificar `to_internet` / `to_network` y servicios | WebUI Dashboard | LibreQoS está en ejecución, pero no hace shaping |
+| Scheduler no saludable | revisar logs de `lqosd` y `lqos_scheduler` | WebUI -> Scheduler Status | El estado del scheduler en WebUI aparece no saludable |
+| Vistas de topología/flujo vacías | confirmar tráfico reciente y estado de `lqosd` | WebUI -> Flow Map / Tree / ASN Explorer | Flow Map / Tree Overview / ASN Explorer aparecen en blanco |
+| Aparece código urgente | abrir detalle y mapear código | WebUI -> Urgent Issues | Códigos de problemas urgentes y primeras acciones |
+| Eventos de límite de circuitos | validar licencia y conteos mapped | Insight UI + WebUI -> Urgent Issues | Se alcanzó el límite de circuitos mapeados |
+
+## Problemas comunes
+
+### Dónde en la WebUI
+
+- Estado de servicios y salud general: `WebUI -> Dashboard`
+- Estado/readiness del scheduler: `WebUI -> Scheduler Status`
+- Alertas prioritarias: `WebUI -> Urgent Issues`
+- Visualización de topología/tráfico: `WebUI -> Network Tree Overview` y `Flow Map`
+- Revisión de datos de shaping: `WebUI -> Shaped Devices Editor`
+
+### La contraseña de usuario no funciona
+
+Elimine el archivo de usuarios:
+
+```bash
+sudo rm /opt/libreqos/src/lqusers.toml
+sudo systemctl restart lqosd lqos_scheduler
+```
+
+Luego abra: `IP_CAJA:9123/index.html`.
+
+### No hay WebUI en x.x.x.x:9123
+
+La WebUI depende de `lqosd`. Cuando no carga, normalmente `lqosd` está fallando.
+
+```bash
+sudo systemctl status lqosd
+journalctl -u lqosd --since "10 minutes ago"
+```
+
+`lqosd` suele mostrar causa específica (interfaz caída, falta de multi-queue, etc.).
+
+### LibreQoS está en ejecución, pero no hace shaping
+
+Verifique en `/etc/lqos.conf` que `to_internet` y `to_network` estén correctos.
+
+```bash
+sudo systemctl restart lqosd lqos_scheduler
+sudo systemctl status lqosd lqos_scheduler
+```
+
+### On-a-stick: shaping incorrecto o una dirección débil
+
+On-a-stick depende de split correcto por dirección. Si la detección TX o `override_available_queues` está mal, el mapeo puede degradarse.
+
+```bash
+sudo systemctl status lqosd
+journalctl -u lqosd --since "10 minutes ago"
+sudo systemctl restart lqosd lqos_scheduler
+```
+
+### El servicio lqosd no se ejecuta o falla al iniciar
+
+```bash
+sudo systemctl status lqosd
+journalctl -u lqosd --since "10 minutes ago"
+```
+
+### Depuración avanzada de lqosd
+
+```bash
+sudo RUST_LOG=info /opt/libreqos/src/bin/lqosd
+```
+
+### El servicio lqos_scheduler muestra errores
+
+```bash
+sudo journalctl -u lqos_scheduler --since "1 day ago" --no-pager > lqos_sched_log.txt
+```
+
+### El estado del scheduler en WebUI aparece no saludable
+
+Versiones recientes muestran estado/readiness del scheduler en WebUI.
+
+Si aparece caído/desactualizado:
+
+1. Verifique ambos servicios.
+2. Revise logs recientes del scheduler.
+3. Revise logs de `lqosd` para eventos de scheduler ready/error.
+4. Si hubo cambios recientes, reinicie servicios.
+
+```bash
+sudo systemctl status lqosd lqos_scheduler
+journalctl -u lqos_scheduler --since "30 minutes ago"
+journalctl -u lqosd --since "30 minutes ago"
+sudo systemctl restart lqosd lqos_scheduler
+```
+
+Si oscila entre ready/error, valide credenciales y timeouts de integración en `/etc/lqos.conf`.
+
+### RTNETLINK answers: Invalid argument
+
+Suele indicar que no se pudo agregar correctamente qdisc MQ en la NIC (colas RX/TX insuficientes). Verifique [NICs recomendadas](requirements-es.md).
+
+### Python ModuleNotFoundError en Ubuntu 24.04
+
+```bash
+pip uninstall binpacking --break-system-packages --yes
+sudo pip uninstall binpacking --break-system-packages --yes
+sudo pip install binpacking --break-system-packages
+pip uninstall apscheduler --break-system-packages --yes
+sudo pip uninstall apscheduler --break-system-packages --yes
+sudo pip install apscheduler --break-system-packages
+pip uninstall deepdiff --break-system-packages --yes
+sudo pip uninstall deepdiff --break-system-packages --yes
+sudo pip install deepdiff --break-system-packages
+```
+
+### Todas las IPs de clientes aparecen como Unknown IPs
+
+```bash
+cd /opt/libreqos/src
+sudo systemctl stop lqos_scheduler
+sudo python3 LibreQoS.py
+```
+
+Corrija errores en `ShapedDevices.csv` y/o `network.json`, luego:
+
+```bash
+sudo systemctl start lqos_scheduler
+```
+
+### Flow Map / Tree Overview / ASN Explorer aparecen en blanco
+
+Algunas vistas requieren suficiente dato reciente para renderizar.
+
+1. Confirme que `lqosd` está saludable.
+2. Espere acumulación de tráfico.
+3. Recargue la página tras 1-2 minutos.
+4. Revise logs:
+
+```bash
+journalctl -u lqosd --since "10 minutes ago"
+```
+
+Si sigue en blanco con tráfico normal, recolecte logs y abra issue.
+
+### Colisión de promoción de nodo virtual (`network.json`)
+
+Si `LibreQoS.py` falla con `Virtual node promotion collision: 'AP_A' already exists at this level.`, hay un nodo con `"virtual": true` cuyos hijos colisionan por nombre al promoverse.
+
+Renombre nodos en conflicto o reestructure jerarquía para evitar colisiones.
+
+### Se alcanzó el límite de circuitos mapeados
+
+Si ve mensajes como:
+
+- `Mapped circuit limit reached`
+- `Bakery mapped circuit cap enforced`
+
+LibreQoS está aplicando un límite de circuitos mapeados.
+
+Checks recomendados:
+
+1. Confirmar estado de licencia Insight en UI.
+2. Revisar logs de `lqosd` para requested/allowed/dropped.
+3. Reducir circuitos mapeados (corto plazo) o ajustar licencia/límites (largo plazo).
+
+### Códigos de problemas urgentes y primeras acciones
+
+WebUI muestra códigos legibles por máquina para triage rápido.
+
+| Código | Significado | Primeros checks | Ruta de corrección típica |
+|---|---|---|---|
+| `MAPPED_CIRCUIT_LIMIT` | Bakery está forzando límite de circuitos mapeados. | Estado de licencia Insight y `journalctl -u lqosd` con requested/allowed/dropped. | Reducir circuitos mapeados o actualizar licencia/límites. |
+| `TC_U16_OVERFLOW` | IDs minor de clases/colas excedieron rango u16 de tc en una cola CPU. | `journalctl -u lqos_scheduler -u lqosd`, profundidad topológica y distribución por colas. | Aumentar paralelismo de colas y/o simplificar/rebalancear jerarquía. |
+
+Patrón operativo:
+
+1. Abra el detalle del problema urgente en WebUI (código/mensaje/contexto).
+2. Recolecte logs correlacionados de `lqosd` y `lqos_scheduler`.
+3. Aplique mitigación inmediata.
+4. Reconozca/limpie el evento en UI cuando esté estable.
+
+### Segfault de systemd
+
+Si experimenta un segfault en systemd, es un problema conocido [1](https://github.com/systemd/systemd/issues/36031) [2](https://github.com/systemd/systemd/issues/33643).
+
+#### Instalar dependencias de compilación
+
+```bash
+sudo apt update
+sudo apt install build-essential git meson libcap-dev libmount-dev libseccomp-dev \
+libblkid-dev libacl1-dev libattr1-dev libcryptsetup-dev libaudit-dev \
+libpam0g-dev libselinux1-dev libzstd-dev libcurl4-openssl-dev
+```
+
+#### Clonar systemd desde GitHub
+
+```bash
+git clone https://github.com/systemd/systemd.git
+cd systemd
+git checkout v257.5
+meson setup build
+meson compile -C build
+sudo meson install -C build
+```
+
+Luego reinicie y valide con:
+
+```bash
+systemctl --version
+```
+
+## Páginas relacionadas
+
+- [Quickstart](quickstart-es.md)
+- [Configurar LibreQoS](configuration-es.md)
+- [Integraciones CRM/NMS](integrations-es.md)
+- [Escalado y diseño de topología](scale-topology-es.md)
+- [Ajuste de rendimiento](performance-tuning-es.md)
diff --git a/_build/html/_sources/docs-es/v2.0/ubuntu-server-es.md.txt b/_build/html/_sources/docs-es/v2.0/ubuntu-server-es.md.txt
new file mode 100644
index 00000000..8c23c2b6
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/ubuntu-server-es.md.txt
@@ -0,0 +1,40 @@
+# Instalar Servidor de Ubuntu
+
+Puedes descargar Ubuntu Server 24.04 LTS desde aquí.
+Por el momento, solo se admite Ubuntu Server 24.04. Asegúrate de no utilizar otras versiones.
+
+1. Arranca Ubuntu Server desde una USB.
+2. Sigue los pasos a continuación para instalar Ubuntu Server.
+
+
+
+
+
+
+
+Para las interfaces de red, desactiva completamente las interfaces utilizadas. Después, asigna una dirección IP estática a la interfaz de administración (100.99.0.4 es solo un ejemplo).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Asegúrese de que el servidor SSH esté habilitado para que pueda iniciar sesión en el servidor más fácilmente después.
+
+
+
+
+
+
+Puedes utilizar scp o sftp para acceder a los archivos de tu servidor LibreQoS y facilitar la modifición de archivos. Aquí se explica cómo acceder mediante scp o sftp usando una máquina [Ubuntu](https://www.addictivetips.com/ubuntu-linux-tips/sftp-server-ubuntu/) o [Windows](https://winscp.net/eng/index.php).
+
diff --git a/_build/html/_sources/docs-es/v2.0/update-es.md.txt b/_build/html/_sources/docs-es/v2.0/update-es.md.txt
new file mode 100644
index 00000000..61d1d8e0
--- /dev/null
+++ b/_build/html/_sources/docs-es/v2.0/update-es.md.txt
@@ -0,0 +1,38 @@
+# Actualización
+
+```{warning}
+Si usas el puente XDP, el tráfico dejará de pasar por el puente mientras lqosd se reinicia (el puente XDP solo opera mientras lqosd está en ejecución).
+```
+
+## Si instalaste el .deb
+
+```
+cd ~
+sudo apt-get update
+sudo apt-get upgrade
+wget https://download.libreqos.com/{deb_url_v1_5}
+sudo apt install ./{deb_url_v1_5}
+sudo systemctl restart lqosd lqos_scheduler
+```
+
+Ahora reinicia tu servidor LibreQoS con:
+
+```
+sudo reboot
+```
+
+Esto limpiará los mapas eBPF antiguos y cargará la última versión de LibreQoS.
+
+## Si instalaste desde Git
+
+1. Cambia a tu directorio `LibreQoS` (por ejemplo `cd /opt/LibreQoS`)
+2. Actualiza desde Git: `git pull`
+3. ```git switch develop```
+4. Recompila: `./build-rust.sh`
+5. `sudo rust/remove_pinned_maps.sh`
+
+Ejecuta los siguientes comandos para recargar los servicios de LibreQoS:
+
+```shell
+sudo systemctl restart lqosd lqos_scheduler
+```
diff --git a/_build/html/_sources/docs/v2.0/api.md.txt b/_build/html/_sources/docs/v2.0/api.md.txt
new file mode 100644
index 00000000..8cbb6d48
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/api.md.txt
@@ -0,0 +1,176 @@
+# LibreQoS Node API
+
+## Requirements
+
+The LibreQoS Node API requires an active LibreQoS Insight subscription.
+
+## Installation
+
+### If installed via `.deb` (recommended)
+
+`lqos_api` is installed with LibreQoS into:
+
+`/opt/libreqos/src/bin/lqos_api`
+
+### Test run
+
+```bash
+/opt/libreqos/src/bin/lqos_api
+```
+
+### Systemd Service
+
+The package includes a template service file:
+
+```bash
+sudo cp /opt/libreqos/src/bin/lqos_api.service.example /etc/systemd/system/lqos_api.service
+```
+
+Then run:
+
+```bash
+sudo systemctl daemon-reload
+sudo systemctl enable lqos_api
+sudo systemctl start lqos_api
+```
+
+### Update just the API binary
+
+Use the helper script:
+
+```bash
+cd /opt/libreqos/src
+./update_api.sh
+```
+
+This downloads the latest `lqos_api` and installs it to `/opt/libreqos/src/bin/lqos_api`.
+
+You can optionally skip service restart:
+
+```bash
+./update_api.sh --no-restart
+```
+
+Or install to an alternate location:
+
+```bash
+./update_api.sh --bin-dir /some/path/bin --no-restart
+```
+
+### Manual service file (if needed)
+
+If you are creating the service manually, use:
+
+```
+[Unit]
+After=network.service lqosd.service
+Requires=lqosd.service
+
+[Service]
+WorkingDirectory=/opt/libreqos/src/bin
+ExecStart=/opt/libreqos/src/bin/lqos_api
+Restart=always
+
+[Install]
+WantedBy=default.target
+```
+
+Then run:
+
+```bash
+sudo systemctl daemon-reload
+sudo systemctl enable lqos_api
+sudo systemctl start lqos_api
+```
+
+## Usage
+
+See `localhost:9122/api-docs` for the Swagger UI.
+
+`/api-docs` is the source of truth for your installed version. Endpoint availability can change between releases.
+
+## Deployment and Hardening Guidance
+
+Recommended production posture:
+
+1. Keep the Node API reachable only from trusted management networks.
+2. Do not expose the API directly to the public Internet.
+3. If remote access is required, place it behind a reverse proxy with TLS and authentication.
+4. Restrict inbound access with host/network firewall allowlists.
+5. Monitor API and service logs for abnormal access patterns.
+
+If the API is not needed on a node, disable the service:
+
+```bash
+sudo systemctl disable --now lqos_api
+```
+
+If enabled for operations, verify service state after upgrades:
+
+```bash
+sudo systemctl status lqos_api
+```
+
+## API Endpoints
+
+### Health & System
+- `/health` - Service health check
+- `/reload_libreqos` - Reload LibreQoS configuration
+- `/validate_shaped_devices` - Validate shaped devices CSV
+- `/lqos_stats` - Get lqosd internal statistics
+- `/stormguard_stats` - Get Stormguard statistics
+- `/bakery_stats` - Get Bakery active circuits count
+
+### Traffic Metrics
+- `/current_throughput` - Current network throughput stats
+- `/top_n_downloaders/{start}/{end}` - Top downloaders by traffic
+- `/worst_rtt/{start}/{end}` - Hosts with worst round-trip time
+- `/worst_retransmits/{start}/{end}` - Hosts with worst TCP retransmits
+- `/best_rtt/{start}/{end}` - Hosts with best round-trip time
+- `/host_counter` - All host traffic counters
+
+### Network Topology
+- `/network_map/{parent}` - Network map from parent node
+- `/full_network_map` - Complete network topology
+- `/top_map_queues/{n}` - Top N queues by traffic
+- `/node_names` - Get node names from IDs
+- `/funnel/{target}` - Analyze traffic funnel to circuit
+
+### Circuit Management
+- `/all_circuits` - List all circuits
+- `/raw_queue_data/{circuit_id}` - Raw queue data for circuit
+
+### Flow Analysis
+- `/dump_active_flows` - Dump all active flows (slow)
+- `/count_active_flows` - Count of active flows
+- `/top_flows/{flow_type}/{n}` - Top flows by metric type
+- `/flows_by_ip/{ip}` - Flows for specific IP
+- `/flow_duration` - Flow duration statistics
+
+### Geo & Protocol Stats
+- `/current_endpoints_by_country` - Traffic endpoints by country
+- `/current_endpoint_latlon` - Endpoint geographic coordinates
+- `/ether_protocol_summary` - Ethernet protocol statistics
+- `/ip_protocol_summary` - IP protocol statistics
+
+## Newer API Coverage Areas
+
+Recent builds expanded API coverage in a few areas. Depending on your version, the API may also include:
+
+- Alerts and warnings summaries
+- Device and circuit count summaries
+- Single-circuit detail lookups
+- Search result helpers for UI workflows
+- Scheduler and queue-stat detail endpoints
+
+Use `localhost:9122/api-docs` to confirm exact paths and schemas on your node.
+
+## Capturing an endpoint inventory for your release
+
+For release notes or internal runbooks, capture a snapshot of API paths from your node:
+
+```bash
+curl -s http://localhost:9122/api-docs | jq -r '.paths | keys[]' | sort
+```
+
+Save this output with your release artifacts so operators can compare endpoint differences between versions.
diff --git a/_build/html/_sources/docs/v2.0/bridge.md.txt b/_build/html/_sources/docs/v2.0/bridge.md.txt
new file mode 100644
index 00000000..fe465057
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/bridge.md.txt
@@ -0,0 +1,89 @@
+# Configure Shaping Bridge
+
+## Choose Bridge Type
+
+There are two options for the bridge to pass data through your two interfaces:
+
+- Option A: Regular Linux Bridge (Recommended)
+- Option B: Bifrost XDP-Accelerated Bridge
+
+The regular Linux bridge is recommended for most installations. The Linux Bridge continues to move data even if the lqosd service is in a failed state, making this a generally safer option in scenatios where a backup route is not in place. It works best with Nvidia/Mellanox NICs such as the ConnectX-5 series (which have superior bridge performance), and VM setups using virtualized NICs. The Bifrost XDP Bridge is recommended for 40G-100G Intel NICs with XDP support.
+
+Below are the instructions to configure Netplan, whether using the Linux Bridge or Bifrost XDP bridge:
+
+## Option A: Netplan config for a regular Linux bridge (Recommended)
+
+Ubuntu Server uses NetPlan, which uses .yaml files in /etc/netplan to determine interface settings.
+Here, we will add a .yaml specifically for LibreQoS - that way it is not overwritten when changes are made to the default .yaml file.
+
+```shell
+sudo nano /etc/netplan/libreqos.yaml
+```
+
+Assuming your shaping interfaces are ens19 and ens20, here is what your file would look like:
+
+```yaml
+network:
+ ethernets:
+ ens19:
+ dhcp4: no
+ dhcp6: no
+ ens20:
+ dhcp4: no
+ dhcp6: no
+ bridges:
+ br0:
+ interfaces:
+ - ens19
+ - ens20
+ version: 2
+```
+```{note}
+Please be sure to replace ens19 and ens20 in the example above with the correct shaping interfaces. The order of the interfaces does not matter for this section.
+```
+
+By setting `dhcp4: no` and `dhcp6: no`, the shaping interfaces will be brought up as part of the normal boot cycle, despite not having IP addresses assigned.
+
+Then run
+
+```shell
+sudo chmod 600 /etc/netplan/libreqos.yaml
+sudo netplan apply
+```
+
+## Option B: Netplan config for the Bifrost XDP bridge
+
+Ubuntu Server uses NetPlan, which uses .yaml files in /etc/netplan to determine interface settings.
+Here, we will add a .yaml specifically for LibreQoS - that way it is not overwritten when changes are made to the default .yaml file.
+
+```shell
+sudo nano /etc/netplan/libreqos.yaml
+```
+
+Assuming your shaping interfaces are ens19 and ens20, here is what your file would look like:
+
+```yaml
+network:
+ ethernets:
+ ens19:
+ dhcp4: no
+ dhcp6: no
+ ens20:
+ dhcp4: no
+ dhcp6: no
+ version: 2
+```
+```{note}
+Please be sure to replace ens19 and ens20 in the example above with the correct shaping interfaces. The order of the interfaces does not matter for this section.
+```
+
+By setting `dhcp4: no` and `dhcp6: no`, the shaping interfaces will be brought up as part of the normal boot cycle, despite not having IP addresses assigned.
+
+Then run
+
+```shell
+sudo chmod 600 /etc/netplan/libreqos.yaml
+sudo netplan apply
+```
+
+To use the XDP bridge, please be sure to set `use_xdp_bridge` to `true` in lqos.conf in the [Configuration](configuration.md) section.
diff --git a/_build/html/_sources/docs/v2.0/cake.md.txt b/_build/html/_sources/docs/v2.0/cake.md.txt
new file mode 100644
index 00000000..8499500c
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/cake.md.txt
@@ -0,0 +1,54 @@
+# CAKE
+
+By default, LibreQoS uses Common Applications Kept Enhanced (CAKE) using the diffserv4 parameter.
+
+## DSCP
+
+[https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml](https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml)
+
+### Traffic Classes and DSCP Tags for Diffserv4
+
+ * Latency Sensitive (CS7, CS6, EF, VA, CS5, CS4)
+ * Streaming Media (AF4x, AF3x, CS3, AF2x, TOS4, CS2, TOS1)
+ * Best Effort (CS0, AF1x, TOS2, and those not specified)
+ * Background Traffic (CS1)
+
+### List of known Diffserv codepoints:
+
+ * Least Effort (CS1)
+ * Best Effort (CS0)
+ * Max Reliability & LLT "Lo" (TOS1)
+ * Max Throughput (TOS2)
+ * Min Delay (TOS4)
+ * LLT "La" (TOS5)
+ * Assured Forwarding 1 (AF1x) - x3
+ * Assured Forwarding 2 (AF2x) - x3
+ * Assured Forwarding 3 (AF3x) - x3
+ * Assured Forwarding 4 (AF4x) - x3
+ * Precedence Class 2 (CS2)
+ * Precedence Class 3 (CS3)
+ * Precedence Class 4 (CS4)
+ * Precedence Class 5 (CS5)
+ * Precedence Class 6 (CS6)
+ * Precedence Class 7 (CS7)
+ * Voice Admit (VA)
+ * Expedited Forwarding (EF)
+
+### List of traffic classes in RFC 4594:
+
+(roughly descending order of contended priority)
+
+(roughly ascending order of uncontended throughput)
+
+ * Network Control (CS6,CS7) - routing traffic
+ * Telephony (EF,VA) - aka. VoIP streams
+ * Signalling (CS5) - VoIP setup
+ * Multimedia Conferencing (AF4x) - aka. video calls
+ * Realtime Interactive (CS4) - eg. games
+ * Multimedia Streaming (AF3x) - eg. YouTube, NetFlix, Twitch
+ * Broadcast Video (CS3)
+ * Low Latency Data (AF2x,TOS4) - eg. database
+ * Ops, Admin, Management (CS2,TOS1) - eg. ssh
+ * Standard Service (CS0 & unrecognised codepoints)
+ * High Throughput Data (AF1x,TOS2) - eg. web traffic
+ * Low Priority Data (CS1) - eg. BitTorrent
diff --git a/_build/html/_sources/docs/v2.0/components.md.txt b/_build/html/_sources/docs/v2.0/components.md.txt
new file mode 100644
index 00000000..273783b2
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/components.md.txt
@@ -0,0 +1,106 @@
+# LibreQoS Software Components
+
+## Systemd Services
+### lqosd
+
+- Manages actual XDP code.
+- Coded in Rust.
+- Runs the GUI available at http://a.b.c.d:9123
+- Hosts WebUI pages such as:
+ - Flow Map
+ - Network Tree Overview
+ - ASN Explorer
+ - CPU Tree / CPU Weights
+ - Configuration editors for integrations (UISP, Splynx, Netzur, VISP, etc.)
+
+### lqos_scheduler
+
+- lqos_scheduler performs continuous refreshes of LibreQoS' shapers, including pulling from any enabled CRM Integrations (UISP, Splynx, Netzur).
+- Actions:
+ - On start: Run a full setup of queues
+ - Every X minutes: Update queues, pulling new configuration from CRM integration, if enabled.
+ - The default minute interval is 30, so the refresh occurs every 30 minutes by default.
+ - The minute interval is adjustable with the setting `queue_refresh_interval_mins` in `/etc/lqos.conf`.
+
+### Checking service status
+
+```
+sudo systemctl status lqosd lqos_scheduler
+```
+
+If the status of one of the two services shows 'failed', examine why using journalctl, which shows the full status of the service. For example, if lqosd failed, you would run:
+```
+sudo journalctl -u lqosd -b
+```
+Press the End key on the keyboard to take you to the bottom of the log to see the latest updates to that log.
+
+Lqosd will provide specific reasons it failed, such as an interface not being up, an interface lacking multi-queue, or other cocnerns.
+
+### Debugging lqos_scheduler
+
+In the background, lqos_scheduler runs the Python script scheduler.py, which in turn runs the Python script LibreQoS.py
+
+- scheduler.py: performs continuous refreshes of LibreQoS' shapers, including pulling from any enabled CRM Integrations (UISP, Splynx, Netzur).
+- LibreQoS.py: creates and updates queues / shaping of devices
+
+One-time runs of these individual components can be very helpful for debugging and to make sure everything is correctly configured.
+
+First, stop lqos_scheduler
+
+```shell
+sudo systemctl stop lqos_scheduler
+```
+
+For one-time runs of LibreQoS.py, use
+
+```shell
+sudo ./LibreQoS.py
+```
+
+- To use the debug mode with more verbose output, use:
+
+```shell
+sudo ./LibreQoS.py --debug
+```
+
+To confirm that lqos_scheduler (scheduler.py) is able to work correctly, run:
+
+```shell
+sudo python3 scheduler.py
+```
+
+Once you have any errors eliminated, restart lqos_scheduler with
+
+```shell
+sudo systemctl start lqos_scheduler
+```
+
+### Troubleshooting Service Components
+Please see [Troubleshooting](troubleshooting.md).
+
+## WebUI privacy mode
+
+WebUI (Node Manager) includes a client-side redaction mode for demos/screenshots:
+- Toggle using the mask icon in the top navigation.
+- Redaction preference is saved in browser local storage.
+- This masks/redacts visible data in the browser UI; it does not modify source data files.
+
+For public screenshots, enable redaction before capture.
+
+## Urgent issue channel
+
+WebUI (Node Manager) includes an urgent issue channel for high-priority events (for example, mapped-circuit limit enforcement and related operational warnings).
+
+- Urgent issues appear in the top navigation indicator.
+- They can be reviewed and acknowledged from the urgent issues modal.
+- Use this as an at-a-glance operational signal; confirm details in `journalctl -u lqosd`.
+
+## Scheduler status indicator
+
+WebUI (Node Manager) includes scheduler status visibility for operator awareness.
+
+- Use scheduler status as a quick health signal for recurring refresh jobs.
+- If scheduler is not healthy, validate `lqosd` and `lqos_scheduler` service state first.
+- Confirm details with:
+ - `journalctl -u lqos_scheduler --since "30 minutes ago"`
+ - `journalctl -u lqosd --since "30 minutes ago"`
diff --git a/_build/html/_sources/docs/v2.0/configuration-advanced.md.txt b/_build/html/_sources/docs/v2.0/configuration-advanced.md.txt
new file mode 100644
index 00000000..e978bb36
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/configuration-advanced.md.txt
@@ -0,0 +1,251 @@
+# Advanced Configuration Reference
+
+Use this page when you need CLI-driven configuration, direct file editing, or deep reference details.
+
+## Configuration via Command Line
+
+You can also modify settings using the command line.
+
+### Main Configuration File
+#### /etc/lqos.conf
+
+The configuration for each LibreQoS shaper box is stored in the file `/etc/lqos.conf`.
+
+Edit the file to match your setup with
+
+```shell
+sudo nano /etc/lqos.conf
+```
+
+In the ```[bridge]``` section, change `to_internet` and `to_network` to match your network interfaces.
+- `to_internet = "enp1s0f1"`
+- `to_network = "enp1s0f2"`
+
+In the `[bridge]` section of the lqos.conf file, you can enable or disable the XDP Bridge with the setting `use_xdp_bridge`. The default value is `false` - because the default setup assumes a [Linux Bridge](prereq.md). If you chose to use the XDP Bridge during that pre-requisites setup, please set `use_xdp_bridge = true` instead.
+
+- Set downlink_bandwidth_mbps and uplink_bandwidth_mbps to match the bandwidth in Mbps of your network's upstream / WAN internet connection. The same can be done for generated_pn_download_mbps and generated_pn_upload_mbps.
+- to_internet would be the interface facing your edge router and the broader internet
+- to_network would be the interface facing your core router (or bridged internal network if your network is bridged)
+
+Note: If you find that traffic is not being shaped when it should, please make sure to swap the interface order and restart lqosd as well as lqos_scheduler with ```sudo systemctl restart lqosd lqos_scheduler```.
+
+After changing any part of `/etc/lqos.conf` it is highly recommended to always restart lqosd, using `sudo systemctl restart lqosd`. This re-parses any new values in lqos.conf, making those new values accessible to both the Rust and Python sides of the code.
+
+#### Netflow (optional)
+To enable netflow, add the following `[flows]` section to the `/etc/lqos.conf` configuration file, setting the appropriate `netflow_ip`:
+```
+[flows]
+flow_timeout_seconds = 30
+netflow_enabled = true
+netflow_port = 2055
+netflow_ip = "100.100.100.100"
+netflow_version = 5
+do_not_track_subnets = ["192.168.0.0/16"]
+```
+
+#### On-a-stick mode queue mapping (single interface)
+
+When running on-a-stick mode, LibreQoS splits available TX queues in half:
+- first half for one direction
+- second half for the reverse direction
+
+So if 16 queues are available, each direction gets 8 queues. This directional offset is computed automatically at startup.
+
+If your NIC exposes unusual queue counts, you can set `override_available_queues` in `[queues]` and restart `lqosd`.
+
+If shaping appears asymmetric in on-a-stick deployments, verify:
+- the interface has enough TX queues
+- `override_available_queues` is not forcing an incorrect value
+- you have restarted after config changes
+
+See also [Troubleshooting](troubleshooting.md).
+
+#### CRM/NMS Integrations
+
+Learn more about [configuring integrations here](integrations.md).
+
+### Runtime overrides (`lqos_overrides.json`)
+
+LibreQoS supports runtime-friendly adjustments via `lqos_overrides.json` in your `lqos_directory`.
+
+Use the `lqos_overrides` CLI:
+
+```bash
+/opt/libreqos/src/bin/lqos_overrides --help
+```
+
+Common examples:
+
+```bash
+# List persistent devices
+/opt/libreqos/src/bin/lqos_overrides persistent-devices list
+
+# Add/replace per-circuit speed adjustment
+/opt/libreqos/src/bin/lqos_overrides adjustments add-circuit-speed --circuit-id "1234" --max-download-bandwidth 200 --max-upload-bandwidth 50
+
+# Set a node to logical-only (virtual) without editing network.json directly
+/opt/libreqos/src/bin/lqos_overrides network-adjustments set-virtual "AP_GROUP_A" true
+
+# List network adjustments
+/opt/libreqos/src/bin/lqos_overrides network-adjustments list
+```
+
+How overrides apply:
+- `lqos_scheduler` applies overrides during refresh cycles.
+- persistent devices are merged into `ShapedDevices.csv`.
+- circuit/device/network adjustments are applied on top of imported/manual data.
+
+### Network Hierarchy
+#### Network.json
+
+Network.json allows ISP operators to define a Hierarchical Network Topology, or Flat Network Topology.
+
+If you plan to use the built-in UISP, Splynx, or Netzur integrations, you do not need to create a network.json file quite yet.
+If you plan to use the built-in UISP integration, it will create this automatically on its first run (assuming network.json is not already present).
+
+If you will not be using an integration, you can manually define the network.json following the template file - [network.example.json](https://github.com/LibreQoE/LibreQoS/blob/develop/src/network.example.json). Below is a table illustration of network.example.json.
+
+
Entire Network
Site_1
Site_2
AP_A
Site_3
Pop_1
AP_1
PoP_5
AP_7
AP_9
PoP_6
AP_11
+
+For networks with no Parent Nodes (no strictly defined Access Points or Sites) edit the network.json to use a Flat Network Topology with
+```
+echo "{}" > network.json
+```
+
+##### Virtual (logical-only) nodes
+
+LibreQoS supports **virtual nodes** in `network.json` for organizational grouping and monitoring/aggregation in the WebUI/Insight. Virtual nodes are **not** included in the physical HTB shaping tree (they won’t create HTB classes and won’t enforce bandwidth limits).
+
+To mark a node as virtual, set `"virtual": true` on that node.
+
+Example:
+
+```json
+{
+ "Region": {
+ "downloadBandwidthMbps": 1000,
+ "uploadBandwidthMbps": 1000,
+ "children": {
+ "Town": {
+ "virtual": true,
+ "downloadBandwidthMbps": 500,
+ "uploadBandwidthMbps": 500,
+ "children": {
+ "AP_A": {
+ "downloadBandwidthMbps": 200,
+ "uploadBandwidthMbps": 200
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+Notes:
+- During shaping, virtual nodes are removed and their children are promoted to the nearest non-virtual ancestor (see `queuingStructure.json` for the active physical plan).
+- `ShapedDevices.csv` can still use a virtual node as a `Parent Node` for display/grouping; LibreQoS will attach those circuits for shaping to the nearest non-virtual ancestor (top-level virtual nodes will be treated as unparented for shaping).
+- Avoid name collisions after promotion (two nodes with the same name ending up at the same level).
+
+#### CPU Considerations
+
+
+
+##### CSV to JSON conversion helper
+
+You can use
+
+```shell
+python3 csvToNetworkJSON.py
+```
+
+to convert manualNetwork.csv to a network.json file.
+manualNetwork.csv can be copied from the template file, manualNetwork.template.csv
+
+Note: The parent node name must match that used for clients in ShapedDevices.csv
+
+### Circuits
+
+LibreQoS shapes individual devices by their IP addresses, which are grouped into "circuits".
+
+A circuit represents an ISP subscriber's internet service, which may have just one associated IP (the subscriber's router may be assigned a single /32 IPv4 for example) or it might have multiple IPs associated (maybe their router has a /29 assigned, or multiple /32s).
+
+LibreQoS knows how to shape these devices, and what Node (AP, Site, etc) they are contained by, with the ShapedDevices.csv file.
+
+#### ShapedDevices.csv
+
+The ShapedDevices.csv file correlates device IP addresses to Circuits (each internet subscriber's unique service).
+
+The base format has 13 columns, with an optional 14th `sqm` column for per-circuit queue overrides:
+
+```
+Circuit ID,Circuit Name,Device ID,Device Name,Parent Node,MAC,IPv4,IPv6,Download Min Mbps,Upload Min Mbps,Download Max Mbps,Upload Max Mbps,Comment[,sqm]
+```
+
+##### Optional `sqm` column
+
+If present, `sqm` overrides queueing for that circuit.
+
+Allowed values:
+- Single token: `cake`, `fq_codel`, `none`
+- Directional token: `down_sqm/up_sqm` where each side is `cake`, `fq_codel`, `none`, or empty
+
+Examples:
+- `cake` (both directions)
+- `cake/fq_codel` (download cake, upload fq_codel)
+- `fq_codel/` (download fq_codel, upload uses global default)
+- `/none` (upload disabled, download uses global default)
+
+If `sqm` is empty/missing, global queue defaults apply.
+
+Here is an example of an entry in the ShapedDevices.csv file:
+| Circuit ID | Circuit Name | Device ID | Device Name | Parent Node | MAC | IPv4 | IPv6 | Download Min Mbps | Upload Min Mbps | Download Max Mbps | Upload Max Mbps | Comment |
+|------------|-----------------------------------------------------|-----------|-------------|-------------|-----|-------------------------|----------------------|-------------------|-----------------|-------------------|-----------------|---------|
+| 1 | 968 Circle St., Gurnee, IL 60031 | 1 | Device 1 | AP_A | | 100.64.0.1, 100.64.0.14 | fdd7:b724:0:100::/56 | 1 | 1 | 155 | 20 | |
+| 2 | 31 Marconi Street, Lake In The Hills, IL 60156 | 2 | Device 2 | AP_A | | 100.64.0.2 | fdd7:b724:0:200::/56 | 1 | 1 | 105 | 18 | |
+| 3 | 255 NW. Newport Ave., Jamestown, NY 14701 | 3 | Device 3 | AP_9 | | 100.64.0.3 | fdd7:b724:0:300::/56 | 1 | 1 | 105 | 18 | |
+| 4 | 8493 Campfire Street, Peabody, MA 01960 | 4 | Device 4 | AP_9 | | 100.64.0.4 | fdd7:b724:0:400::/56 | 1 | 1 | 105 | 18 | |
+| 2794 | 6 Littleton Drive, Ringgold, GA 30736 | 5 | Device 5 | AP_11 | | 100.64.0.5 | fdd7:b724:0:500::/56 | 1 | 1 | 105 | 18 | |
+| 2794 | 6 Littleton Drive, Ringgold, GA 30736 | 6 | Device 6 | AP_11 | | 100.64.0.6 | fdd7:b724:0:600::/56 | 1 | 1 | 105 | 18 | |
+| 5 | 93 Oklahoma Ave., Parsippany, NJ 07054 | 7 | Device 7 | AP_1 | | 100.64.0.7 | fdd7:b724:0:700::/56 | 1 | 1 | 155 | 20 | |
+| 6 | 74 Bishop Ave., Bakersfield, CA 93306 | 8 | Device 8 | AP_1 | | 100.64.0.8 | fdd7:b724:0:800::/56 | 1 | 1 | 105 | 18 | |
+| 7 | 9598 Peg Shop Drive, Lutherville Timonium, MD 21093 | 9 | Device 9 | AP_7 | | 100.64.0.9 | fdd7:b724:0:900::/56 | 1 | 1 | 105 | 18 | |
+| 8 | 115 Gartner Rd., Gettysburg, PA 17325 | 10 | Device 10 | AP_7 | | 100.64.0.10 | fdd7:b724:0:a00::/56 | 1 | 1 | 105 | 18 | |
+| 9 | 525 Birchpond St., Romulus, MI 48174 | 11 | Device 11 | Site_1 | | 100.64.0.11 | fdd7:b724:0:b00::/56 | 1 | 1 | 105 | 18 | |
+
+If you are using one of our CRM integrations, this file will be automatically generated. If you are not using an integration, you can manually edit the file using either the WebUI or by directly editing the ShapedDevices.csv file through the CLI.
+
+Directional SQM examples:
+
+```
+2794,"6 Littleton Drive, Ringgold, GA 30736",5,Device 5,AP_11,,100.64.0.5,"fdd7:b724:0:500::/56",1,1,105,18,"",cake/fq_codel
+2795,"7 Example Ave",6,Device 6,AP_11,,100.64.0.6,,1,1,105,18,"",/none
+```
+
+##### Multiple IPs per Circuit
+If you need to list multiple IPv4s in the IPv4 field, or multiple IPv6s in the IPv6 field, add a comma between them. If you are editing with a CSV editor (LibreOffice Calc, Excel), the CSV editor will automatically wrap these comma-seperated items with quotes for you. If you are editing the file manually with a utility like notepad or nano, please add quotes surrounding the comma-seperated entries.
+
+```
+2794,"6 Littleton Drive, Ringgold, GA 30736",5,Device 5,AP_11,,100.64.0.5,"fdd7:b724:0:500::/56,fdd7:b724:0:600::/56",1,1,105,18,""
+```
+
+##### Manual Editing by WebUI
+Navigate to the LibreQoS WebUI (http://a.b.c.d:9123) and select Configuration > Shaped Devices.
+
+##### Manual Editing by CLI
+
+- Modify the ShapedDevices.csv file using your preferred spreadsheet editor (LibreOffice Calc, Excel, etc), following the template file - ShapedDevices.example.csv
+- Circuit ID is required. The Circuit ID can be a number or string. This field must NOT include any number symbols (#). Every circuit requires a unique CircuitID - they cannot be reused. Here, circuit essentially refers to a customer's service. If a customer has multiple locations on different parts of your network, use a unique CircuitID for each of those locations.
+- At least one IPv4 address or IPv6 address is required for each entry.
+- The Access Point or Site name should be set in the Parent Node field. Parent Node can be left blank for flat networks.
+- The ShapedDevices.csv file allows you to set minimum (guaranteed), and maximum allowed bandwidth per subscriber.
+- The Download Min and Upload Min for each Circuit must be 1 Mbps or greater. Generally, these should be set to 1 Mbps by default.
+- The Download Max and Upload Max for each Circuit must be 2 Mbps or greater. Generally, these correspond to the customer's speed plan.
+- Recommendation: set the min bandwidth to 1/1 and max to 1.15X advertised plan rate:
+ - This way, when an AP hits its ceiling, users have any remaining AP capacity fairly distributed between them.
+ - By setting the max to 1.15X the speed plan, this makes it more likely that the subscriber will see a satisfactory speed test result, even if there is some small light traffic on their circuit running in the background - such as an HD video stream, software updates, etc.
+ - This allows subscribers to utilize up to the maximum rate when AP has the capacity to allow that.
+
+Note regarding SLAs: For customers with SLA contracts that guarantee them a minimum bandwidth, you can set their plan rate as the minimum bandwidth. That way when an AP approaches its ceiling, SLA customers will always see that rate available. Make sure that the combined minimum rates for circuits connected to a parent node do not exceed the rate of the parent node. If that happens, LibreQoS has a fail-safe that will [reduce the minimums to 1/1](https://github.com/LibreQoE/LibreQoS/pull/643) for all affected circuits.
+
+Once your configuration is complete. You're ready to run the application and start the [systemd services](./components.md#systemd-services)
diff --git a/_build/html/_sources/docs/v2.0/configuration.md.txt b/_build/html/_sources/docs/v2.0/configuration.md.txt
new file mode 100644
index 00000000..059ecabd
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/configuration.md.txt
@@ -0,0 +1,93 @@
+# Configure LibreQoS
+
+## Page Purpose
+
+Use this page for daily operations and WebUI configuration. Use [Advanced Configuration Reference](configuration-advanced.md) for direct file editing and CLI-heavy workflows.
+
+## Initial Configuration Via Setup Tool (From the .deb installer)
+
+
+The setup tool configures initial bridge, interface, bandwidth, IP range, and WebUI user settings.
+
+Notes:
+- The setup tool is keyboard-driven (`Enter` to select, `Q` to quit without saving).
+- If you need to relaunch it after closing:
+ ```
+ sudo apt remove libreqos
+ sudo apt install ./{deb_url_v1_5}
+ ```
+
+### Next Steps
+
+After install, sign in to WebUI at `http://your_shaper_ip:9123`.
+
+For most operators:
+1. Choose your operating mode: [Operating Modes and Source of Truth](operating-modes.md)
+2. Configure integration settings in WebUI: [CRM/NMS Integrations](integrations.md)
+3. Validate scheduler and shaping behavior in WebUI: [LibreQoS WebUI (Node Manager)](node-manager-ui.md)
+
+## Configuration Via Web Interface
+
+Most day-to-day LibreQoS configuration is handled in WebUI (`http://your_shaper_ip:9123/config_general.html`).
+
+### Where in WebUI
+
+- General settings: `Configuration -> General`
+- Integration settings: `Configuration -> Integrations`
+- Shaped devices editor: `Configuration -> Shaped Devices`
+- Runtime operational validation: `WebUI (Node Manager)` pages (dashboard/tree/flow/scheduler)
+
+## Operating Modes and Source of Truth
+
+Read this first before production changes:
+- [Operating Modes and Source of Truth](operating-modes.md)
+
+## QoO (Quality of Outcome) profiles (`qoo_profiles.json`)
+
+LibreQoS displays QoO as an estimate of internet quality based on latency and loss.
+
+### Where the file lives
+
+`/qoo_profiles.json`
+
+### Selecting a profile
+
+- **WebUI**: Configuration -> General -> QoO Profile
+- **Config file**: set `qoo_profile_id` in `/etc/lqos.conf`
+
+Example:
+
+```toml
+# /etc/lqos.conf
+qoo_profile_id = "web_browsing"
+```
+
+### Applying changes
+
+- Changes to `qoo_profiles.json` are picked up automatically.
+- If you change `/etc/lqos.conf`, restart `lqosd`.
+
+## Advanced Configuration Reference
+
+CLI-driven configuration, direct file editing, and deep reference content were moved here:
+- [Advanced Configuration Reference](configuration-advanced.md)
+
+## Configuration via Command Line
+
+This section moved to [Advanced Configuration Reference](configuration-advanced.md#configuration-via-command-line).
+
+## Network Hierarchy
+
+This section moved to [Advanced Configuration Reference](configuration-advanced.md#network-hierarchy).
+
+## Circuits
+
+This section moved to [Advanced Configuration Reference](configuration-advanced.md#circuits).
+
+## Related Pages
+
+- [Quickstart](quickstart.md)
+- [Operating Modes and Source of Truth](operating-modes.md)
+- [CRM/NMS Integrations](integrations.md)
+- [Advanced Configuration Reference](configuration-advanced.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/_build/html/_sources/docs/v2.0/design.md.txt b/_build/html/_sources/docs/v2.0/design.md.txt
new file mode 100644
index 00000000..468f7fdb
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/design.md.txt
@@ -0,0 +1,30 @@
+# Deployment Scenarios
+
+## Standard Inline Deployment
+
+LibreQoS is placed inline at the edge of your network, usually between the network's border router (NAT, firewall) and the core distribution router / switch.
+
+#### NAT/CG-NAT
+If you use NAT/CG-NAT, please place LibreQoS inline prior to where NAT is applied, as LibreQoS needs to shape pre-NAT addresses (100.64.0.0/12) not public post-NAT IPs.
+
+#### MPLS/VPLS
+LibreQoS can parse MPLS traffic, however the traffic must follow the standard pattern:
+```
+(mpls tags)(optional vlan tags)(ip header)
+```
+If you use MPLS with a different tag pattern, you would ideally want to terminate MPLS traffic at the core distribution router / switch, before it reaches LibreQoS.
+
+#### Dynamic Routing: Bypass path
+- Primary path (low cost) *through* the server running LibreQoS
+- Backup path (high cost) *bypassing* the server running LibreQoS.
+
+#### Diagram
+
+
+### Option 1: Using Dynamic Routing (Strongly Recommended)
+
+We recommend using dynamic routing protocols such as OSPF to create a high cost and low cost path between the edge router and core distribution router/switch. The low cost path should pass "through" the LibreQoS shaper bridge interfaces to allow LibreQoS to observe and shape traffic. For example, a low cost OSPF path may be set to a value of 1. The high-cost (backup) link would completely bypass LibreQoS, being set to a higher cost (perhaps 100 for OSPF) to ensure that traffic only takes that path when the LibreQoS shaper bridge is not operational.
+
+## Testbed Deployment (Optional)
+When you are first testing out LibreQoS, you can deploy a small-scale testbed to see it in action on a test network.
+
diff --git a/_build/html/_sources/docs/v2.0/extras.md.txt b/_build/html/_sources/docs/v2.0/extras.md.txt
new file mode 100644
index 00000000..f5620cec
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/extras.md.txt
@@ -0,0 +1,36 @@
+# Extras
+
+## Flamegraph
+
+```shell
+git clone https://github.com/brendangregg/FlameGraph.git
+cd FlameGraph
+sudo perf record -F 99 -a -g -- sleep 60
+perf script > out.perf
+./stackcollapse-perf.pl out.perf > out.folded
+./flamegraph.pl --title LibreQoS --width 7200 out.folded > libreqos.svg
+```
+
+## How to enable CAKE or fq_codel on backup (lower capacity) backhaul links on MikroTik Networks
+
+Set a Queue Tree on the backup point-to-point link's interface, on the Mikrotik router on each end of a link.
+
+For <500M links on reasonable hardware such as a CCR2116, use CAKE:
+
+```
+/queue type
+add kind=fq-codel name=fq_codel
+add cake-diffserv=diffserv4 kind=cake name=cake
+/queue tree
+add max-limit=300M name=BACKUP_LINK_INTERFACE packet-mark=no-mark parent=BACKUP_LINK_INTERFACE queue=cake
+```
+
+For 500-1000M links, use fq_codel:
+
+```
+/queue type
+add kind=fq-codel name=fq_codel
+add cake-diffserv=diffserv4 kind=cake name=cake
+/queue tree
+add max-limit=300M name=BACKUP_LINK_INTERFACE packet-mark=no-mark parent=BACKUP_LINK_INTERFACE queue=fq_codel
+```
diff --git a/_build/html/_sources/docs/v2.0/git-install.md.txt b/_build/html/_sources/docs/v2.0/git-install.md.txt
new file mode 100644
index 00000000..cee5582e
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/git-install.md.txt
@@ -0,0 +1,94 @@
+# Git Install (For Developers - Not Recommended)
+
+## Clone the repo
+
+The recommended install location is `/opt/libreqos`
+Go to the install location, and clone the repo:
+
+```shell
+cd /opt/
+sudo git clone https://github.com/LibreQoE/LibreQoS.git libreqos
+sudo chown -R $USER /opt/libreqos
+cd /opt/libreqos/
+git pull
+```
+
+By specifying `libreqos` at the end, git will ensure the folder name is lowercase.
+
+## Install Dependencies from apt and pip
+
+You need to have a few packages from `apt` installed:
+
+```shell
+sudo apt-get install -y python3-pip clang mold esbuild gcc gcc-multilib llvm libelf-dev git nano graphviz curl screen llvm pkg-config linux-tools-common linux-tools-`uname -r` libbpf-dev libssl-dev
+```
+
+Then you need to install some Python dependencies:
+
+```shell
+cd /opt/libreqos
+PIP_BREAK_SYSTEM_PACKAGES=1 pip install -r requirements.txt
+sudo PIP_BREAK_SYSTEM_PACKAGES=1 pip install -r requirements.txt
+```
+
+## Install the Rust development system
+
+Run the following:
+
+```shell
+curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
+```
+
+When Rust finishes installing, it will tell you to execute a command to place the Rust build tools into your path. You need to either execute this command or logout and back in again.
+
+Once that's done, please run:
+
+```shell
+cd /opt/libreqos/src/
+./build_rust.sh
+```
+
+This will take a while the first time, but it puts everything in the right place.
+
+Now, to build rust crates, run:
+
+```shell
+cd /opt/libreqos/src/rust
+cargo build --all
+```
+
+## Lqos.conf
+
+Copy the lqos.conf configuration file to `/etc`. This is not neccesarry if you installed using the .deb:
+
+```shell
+cd /opt/libreqos/src
+sudo cp lqos.example /etc/lqos.conf
+```
+
+## Configuration
+
+Proceed to configure settings [following this guide](configuration.md).
+
+## Daemon setup
+
+## Run daemons with systemd
+
+Note: If you used the .deb installer, you can skip this section. The .deb installer automatically sets these up.
+
+You can now set up `lqosd`, and `lqos_scheduler` as systemd services.
+
+```shell
+sudo cp /opt/libreqos/src/bin/lqosd.service.example /etc/systemd/system/lqosd.service
+sudo cp /opt/libreqos/src/bin/lqos_scheduler.service.example /etc/systemd/system/lqos_scheduler.service
+```
+
+Finally, run
+
+```shell
+sudo systemctl daemon-reload
+sudo systemctl enable lqosd lqos_scheduler
+sudo systemctl start lqosd lqos_scheduler
+```
+
+You can now point a web browser at `http://a.b.c.d:9123` (replace `a.b.c.d` with the management IP address of your shaping server) and enjoy a real-time view of your network.
diff --git a/_build/html/_sources/docs/v2.0/high-availability.md.txt b/_build/html/_sources/docs/v2.0/high-availability.md.txt
new file mode 100644
index 00000000..0680bd63
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/high-availability.md.txt
@@ -0,0 +1,81 @@
+# High Availability and Failure Domains
+
+This page describes a practical active/backup model for LibreQoS.
+
+## Scope and Assumptions
+
+- This page covers LibreQoS high availability as an active/backup design.
+- Failover should be controlled by dynamic routing (for example OSPF or BGP).
+- Hardware and router vendors are intentionally not prescribed.
+- Insight-specific high availability guidance is out of scope for this page.
+
+## Active/Backup HA Model
+
+One path is active (preferred), and one path is backup (standby). Routing policy controls path selection and failover.
+
+## OSPF Example (Primary Cost 1, Backup Cost 100)
+
+Use OSPF interface cost to prefer the active path.
+
+- Primary LibreQoS path: `ip ospf cost 1`
+- Backup LibreQoS path: `ip ospf cost 100`
+
+Conceptual result:
+
+- Normal state: traffic uses the primary path because cost `1` is lower than `100`.
+- Failure state: if the primary path/router goes down, OSPF converges and traffic uses the backup path.
+- Recovery state: after the primary is healthy again, traffic returns to primary based on lower cost.
+
+Example policy intent:
+
+1. Keep both paths up and routable at all times.
+2. Ensure backup has enough capacity for expected peak load.
+3. Test failover and failback during maintenance windows.
+
+## BGP Equivalent (If You Use BGP Instead of OSPF)
+
+If you run BGP, use standard preference controls to make one path primary and one backup (for example local preference, MED, or AS path prepending based on your design). Keep policy deterministic and documented.
+
+## Recovery and Failback (Conceptual Runbook)
+
+1. Confirm whether failover occurred (routing table/path checks).
+2. Verify customer traffic is flowing on backup path.
+3. Repair the failed primary path.
+4. Validate primary path health.
+5. Return route preference to normal (primary preferred).
+6. Verify traffic has returned to primary and performance is stable.
+
+## Planned Maintenance (Conceptual Procedure)
+
+1. Announce window and success criteria.
+2. Confirm backup path health and capacity.
+3. Shift traffic to backup using routing policy.
+4. Perform maintenance on former active path.
+5. Validate repaired path.
+6. Optionally return traffic to normal active state.
+7. Close window with post-change validation notes.
+
+## HA Readiness Checklist
+
+- Dynamic routing is deployed and documented.
+- Active/backup preferences are explicit and tested.
+- Monitoring and alerting cover both paths and key dependencies.
+- On-call runbook includes failover and failback steps.
+- Regular drill cadence exists (for example quarterly failover tests).
+- Capacity on backup path is validated for realistic peak load.
+
+## Known Limits
+
+- High availability depends on surrounding network design quality.
+- Dynamic routing convergence is not zero-time.
+- Misconfigured policy can cause asymmetric or unstable failover behavior.
+- HA does not replace backups or operational discipline.
+
+## Related Documentation
+
+- [Scale Planning and Topology Design](scale-topology.md)
+- [Performance Tuning](performance-tuning.md)
+- [StormGuard](stormguard.md)
+- [Configuration](configuration.md)
+- [Integrations](integrations.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/_build/html/_sources/docs/v2.0/insight.md.txt b/_build/html/_sources/docs/v2.0/insight.md.txt
new file mode 100644
index 00000000..5159f351
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/insight.md.txt
@@ -0,0 +1,128 @@
+# LibreQoS Insight (Insight)
+
+## About Insight
+Learn more about Insight on our website, [here](https://libreqos.io/insight/).
+
+## Insight UI
+
+### Taskbar
+
+
+
+If you have more than one LibreQoS shaper box, you can select the shaper box you want to view using the Shaper Nodes dropdown box (located just below the search box).
+
+### Time Selector
+
+
+
+By clicking the time selector (Last 24 Hours by default) you can set the time range for data display anywhere from 15 minutes to 28 days. You can also specify custom time periods (Now minus X minutes) or highly-specific detailed time periods.
+
+### Dashboard
+
+You can see which shaper box "perspective" is in use by the listed shpaer box name at the top-left corner next to "Select a destination".
+
+The dashboard for LibreQoS Insight is widget-based, and has multiple tabs - each of which can be edited.
+
+#### Traffic Overview Tab
+
+
+
+The default tab is the Traffic Overview tab - which displays both Live traffic levels as well as top-traffic endpoints - both by ASN and by Node.
+
+#### Shaper Tab
+
+
+
+The Shaper tab shows high-level stats for a particular LibreQoS shaper box.
+
+- Active Circuit Count: The number of active customer circuits observed - based on the subscriber's traffic movement.
+- Throughput: Shaper box throughput
+- Shaper Packets: Packet-per-second rate of the Shaper box over time.
+- Shaper TCP Retransmits Percentage: The percentage of TCP packets observed that were retransmitted. Consider this a proxy for packet loss. This value should typically remain below 1 % across the network.
+- Shaper CAKE Activity: How active the CAKE shapers are on the network over time.
+- Shaper Round Trip Time: The Round Trip Time average of traffic moving across the network.
+- Shaper Round Trip Time Histogram: The Round Trip Time average of traffic moving across the network in histogram format.
+- Shaper CPU Utilization: The peak and average CPU utilization of the shaper box over time.
+- Shaper Memory Utilization: The RAM utilization of the shaper box over time.
+
+#### Children Tab
+
+
+
+- Shaper Child Throughput: The throughput of each top-level child node on the shaper box.
+- Shaper Child TCP Retransmits: This can be used to spot outliers top-level nodes with regard to Retransmits (packet loss).
+- Shaper Child Round Trip Time: This can be used to spot outliers top-level nodes with regard to Round Trip Time.
+
+#### Heatmaps
+
+
+
+This view shows the Round Trip Time, Retransmit, and Capacity heatmaps for the top-level nodes on this shaper box.
+
+#### Site Rankings
+
+
+
+This tab shows the health of Sites / Access Points / etc across the network in terms of their Round Trip Time, TCP Retransmits, and Capacity in each direction.
+
+### Node Map
+
+
+
+This view allows you to identify the general topology of the network from LibreQoS Insight's perspective. If you hover over the bands between nodes, it will display the current throughput and TCP retransmits for that leg of the network.
+
+### Libby (AI Assistant)
+
+
+Libby is LibreQoS Insight's AI Chat Assistant. Libby can help with questions you may have about using LibreQoS or LibreQoS Insight. Libby leverages the official LibreQoS documentation to help you with any questions you may have. Libby can access both live and long-term data - both from synced LibreQoS shaper boxes and from Insight itself. Libby can reply to queries in most major languages with automatic translation.
+
+You may find new ways to use Libby that we had not originally considered. Please feel welcome to share with us ways you have found Libby to help your workflow.
+
+### Site Heatmap
+
+
+This view provides RTT, Retransmit, and Capacity heatmaps for every Access Point, OLT, and Site across your network in one view. This allows you to quickly spot trouble points on your network.
+
+### Tree History
+
+
+
+The Tree History is based on the Tree Overview display from the LibreQoS WebUI, and displays the sankey over time to help quickly identify network bottlenecks impacting performance.
+
+### Reports
+
+
+LibreQoS Insight enables you to trigger AI-generated reports on specific subscriber circuits. These reports draw in from the customer's last 7 days of network activity - including per-ASN performance characteristics, network topology context, and geographic context. The report identifies the User Profile, Key Findings, Critical Issues, Performance Trends, an Upgrade Recommendation, and suggestions for items to manually review.
+
+### Alerts
+
+
+The Alerts section provides you with automated warnings of out-of-norm performance for nodes across the network (Access Points, OLTs, Sites).
+
+## Insight Licensing Behavior (Node-side)
+
+### Local key material and offline grants
+
+LibreQoS stores Insight key material under:
+
+`/.keys/`
+
+Current builds can cache signed license grants locally so nodes can continue operating through temporary connectivity loss to Insight control services. Grant validity and expiration are enforced locally.
+
+Operational notes:
+- Keep `.keys/` persistent across reboots.
+- Treat `.keys/` as sensitive local key material.
+- If grant or key state is invalid, `lqosd` logs will show license/grant errors.
+
+### Mapped circuit limits and license state
+
+Recent builds enforce mapped-circuit limits based on license state.
+
+If your node is unlicensed/invalid, LibreQoS can enforce a default mapped-circuit cap. When the cap is exceeded, logs include messages such as:
+- `Mapped circuit limit reached`
+- `Bakery mapped circuit cap enforced`
+
+When this occurs, check:
+1. Insight license status in the UI.
+2. `journalctl -u lqosd` for requested/allowed/dropped mapped counts.
+3. Whether the number of mapped circuits exceeds your licensed allowance.
diff --git a/_build/html/_sources/docs/v2.0/integrations-netzur.md.txt b/_build/html/_sources/docs/v2.0/integrations-netzur.md.txt
new file mode 100644
index 00000000..670bc895
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/integrations-netzur.md.txt
@@ -0,0 +1,33 @@
+# Netzur Integration
+
+Netzur deployments expose subscriber and zone inventories via a REST endpoint secured with a Bearer token. Configure `/etc/lqos.conf` as follows:
+
+```ini
+[netzur_integration]
+enable_netzur = true
+api_key = "your-netzur-token"
+api_url = "https://netzur.example.com/api/libreqos"
+timeout_secs = 60
+use_mikrotik_ipv6 = false
+```
+
+- `enable_netzur` toggles automatic imports by `lqos_scheduler`.
+- `api_key` is the Bearer token generated inside Netzur.
+- `api_url` must return JSON containing `zones` (mapped to sites) and `customers` (mapped to client circuits and devices).
+- `timeout_secs` overrides the default HTTP timeout (60 seconds) when the API is slow.
+- `use_mikrotik_ipv6` enriches subscriber devices with IPv6 prefixes discovered via `mikrotikDHCPRouterList.csv`.
+
+Run a manual import with:
+
+```bash
+python3 integrationNetzur.py
+```
+
+The integration regenerates `ShapedDevices.csv` and, unless `always_overwrite_network_json` is disabled, updates `network.json`. Adjust the Integration → Common settings if you need to preserve an existing network map between Netzur syncs.
+
+
+## Related Pages
+
+- [CRM/NMS Integrations](integrations.md)
+- [Operating Modes and Source of Truth](operating-modes.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/_build/html/_sources/docs/v2.0/integrations-powercode.md.txt b/_build/html/_sources/docs/v2.0/integrations-powercode.md.txt
new file mode 100644
index 00000000..2105d67d
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/integrations-powercode.md.txt
@@ -0,0 +1,21 @@
+# Powercode Integration
+
+First, set the relevant parameters for Powercode (powercode_api_key, powercode_api_url, etc.) in `/etc/lqos.conf`.
+
+To test the Powercode Integration, use
+
+```shell
+python3 integrationPowercode.py
+```
+
+On the first successful run, it will create a ShapedDevices.csv file.
+You can modify the network.json file manually to reflect Site/AP bandwidth limits.
+ShapedDevices.csv will be overwritten every time the Powercode integration is run.
+You have the option to run integrationPowercode.py automatically on boot and every X minutes (set by the parameter `queue_refresh_interval_mins`), which is highly recommended. This can be enabled by setting ```enable_powercode = true``` in `/etc/lqos.conf`.
+
+
+## Related Pages
+
+- [CRM/NMS Integrations](integrations.md)
+- [Operating Modes and Source of Truth](operating-modes.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/_build/html/_sources/docs/v2.0/integrations-reference.md.txt b/_build/html/_sources/docs/v2.0/integrations-reference.md.txt
new file mode 100644
index 00000000..77e9cb28
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/integrations-reference.md.txt
@@ -0,0 +1,453 @@
+# CRM/NMS Integrations
+
+This page preserves the detailed legacy integration reference.
+For the task-oriented entrypoint, use [CRM/NMS Integrations](integrations.md).
+
+ * [Splynx Integration](#splynx-integration)
+ + [Topology Strategies](#topology-strategies)
+ + [Promote to Root Nodes (Performance Optimization)](#promote-to-root-nodes-performance-optimization)
+ + [Splynx API Access](#splynx-api-access)
+ + [Splynx Overrides](#splynx-overrides)
+ * [Netzur Integration](#netzur-integration)
+ * [VISP Integration](#visp-integration)
+ * [UISP Integration](#uisp-integration)
+ + [Topology Strategies](#topology-strategies-1)
+ + [Suspension Handling Strategies](#suspension-handling-strategies)
+ + [Burst](#burst)
+ + [Configuration Example](#configuration-example)
+ + [UISP Overrides](#uisp-overrides)
+ - [UISP Route Overrides](#uisp-route-overrides)
+ * [WISPGate Integration](#wispgate-integration)
+ * [Powercode Integration](#powercode-integration)
+ * [Sonar Integration](#sonar-integration)
+
+Most operators use this built-in integration path.
+If you use your own scripts as the source of truth for `network.json` and `ShapedDevices.csv`, start with [Operating Modes and Source of Truth](configuration.md#operating-modes-and-source-of-truth).
+
+## What these integrations do
+
+These integrations work by synchronizing with your CRM/NMS system to produce the two files LibreQoS requires for shaping - [network.json](configuration.md#network-hierarchy) and [ShapedDevices.csv](configuration.md#circuits).
+
+Important behavior when integrations are enabled:
+- `ShapedDevices.csv` is typically regenerated by integration sync jobs.
+- `network.json` overwrite behavior depends on your integration settings (for example `always_overwrite_network_json`).
+- Manual edits may be overwritten on the next refresh cycle.
+
+## Splynx Integration
+
+> **⚠️ Breaking Change Notice**: Prior to v1.5-RC-2, the default Splynx strategy was `full`. Starting with v1.5-RC-2, the default strategy is `ap_only` for improved CPU performance. If you require the previous behavior, explicitly set `strategy = "full"` in your Splynx configuration section.
+
+First, set the relevant parameters for Splynx (splynx_api_key, splynx_api_secret, etc.) in `/etc/lqos.conf`.
+
+### Topology Strategies
+
+LibreQoS supports multiple topology strategies for Splynx integration to balance CPU performance with network hierarchy needs:
+
+| Strategy | Description | CPU Impact | Use Case |
+|----------|-------------|------------|----------|
+| `flat` | Only shapes subscribers, no hierarchy | Lowest | Maximum performance, simple subscriber-only shaping |
+| `ap_only` | Single layer: AP → Clients | Low | **Default**. Best balance of performance and structure |
+| `ap_site` | Two layers: Site → AP → Clients | Medium | Site-level aggregation with moderate complexity |
+| `full` | Complete topology mapping | Highest | Full network hierarchy representation |
+
+Configure the strategy in `/etc/lqos.conf` under the `[splynx_integration]` section:
+
+```ini
+[splynx_integration]
+# ... other splynx settings ...
+strategy = "ap_only"
+```
+
+**Performance Considerations:**
+- `flat` and `ap_only` strategies significantly reduce CPU load by limiting network depth
+- Choose `ap_only` for most deployments unless you need site-level traffic aggregation
+- Only use `full` if you require complete network topology representation and have adequate CPU resources
+
+### Promote to Root Nodes (Performance Optimization)
+
+When using `full` topology strategy, you may encounter CPU performance bottlenecks where all traffic flows through a single root site, limiting throughput to what one CPU core can handle.
+
+The **promote_to_root** feature solves this by promoting specific sites to root-level nodes, distributing traffic shaping across multiple CPU cores.
+
+**Configuration:**
+1. Navigate to Integration → Common in the WebUI
+2. In the "Promote to Root Nodes" field, enter one site name per line:
+```
+Remote_Site_Alpha
+Remote_Site_Beta
+Datacenter_West
+```
+
+**Benefits:**
+- Eliminates single-CPU bottleneck for networks with remote sites
+- Distributes traffic shaping across multiple CPU cores
+- Improves overall network performance for large topologies
+- Works with both Splynx and UISP integrations
+
+**When to Use:**
+- Networks with multiple high-capacity remote sites
+- When using `full` topology strategy and experiencing CPU limitations
+- Large networks where root site traffic exceeds single-core capacity
+
+### Splynx API Access
+
+The Splynx Integration uses Basic authentication. For using this type of authentication, please make sure you enable [Unsecure access](https://splynx.docs.apiary.io/#introduction/authentication) in your Splynx API key settings. Also the Splynx API key should be granted access to the necessary permissions.
+
+| Category | Name | Permission |
+|----------------|------------------------------|------------|
+| Tariff Plans | Internet | View |
+| FUP | Compiler | View |
+| FUP | Policies | View |
+| FUP | Capped Data | View |
+| FUP | CAP Tariff | View |
+| FUP | FUP Limits | View |
+| Customers | Customer | View |
+| Customers | Customers Online | View |
+| Customers | Customer Internet services | View |
+| Networking | Routers | View |
+| Networking | Router contention | View |
+| Networking | MikroTik | View |
+| Networking | Monitoring | View |
+| Networking | Network Sites | View |
+| Networking | IPv4 Networks | View |
+| Networking | IPv4 Networks IP | View |
+| Networking | CPE | View |
+| Networking | CPE AP | View |
+| Networking | IPv6 Networks | View |
+| Networking | IPv6 Networks IP (Addresses) | View |
+| Administration | Locations | View |
+
+To test the Splynx Integration, use
+
+```shell
+python3 integrationSplynx.py
+```
+
+On the first successful run, it will create a ShapedDevices.csv file and network.json.
+ShapedDevices.csv will be overwritten every time the Splynx integration is run.
+
+To ensure the network.json is always overwritten with the newest version pulled in by the integration, please edit `/etc/lqos.conf` with the command `sudo nano /etc/lqos.conf`.
+Edit the file to set the value of `always_overwrite_network_json` to `true`.
+Then, run `sudo systemctl restart lqosd`.
+
+You have the option to run integrationSplynx.py automatically on boot and every X minutes (set by the parameter `queue_refresh_interval_mins`), which is highly recommended. This can be enabled by setting ```enable_splynx = true``` under the ```[splynx_integration]``` section in `/etc/lqos.conf`.
+Once set, run `sudo systemctl restart lqos_scheduler`.
+
+### Splynx Overrides
+
+You can also modify the the file `integrationSplynxBandwidths.csv` to override the default bandwidths for each Node (Site, AP).
+
+A template is available in the `/opt/libreqos/src` folder. To utilize the template, copy the file `integrationSplynxBandwidths.template.csv` (removing the `.template` part of the filename) and set the appropriate information inside each file. For example, if you want to change the set bandwidth for a site, you would do:
+```
+sudo cp /opt/libreqos/src/integrationSplynxBandwidths.template.csv /opt/libreqos/src/integrationSplynxBandwidths.csv
+```
+And edit the CSV using LibreOffice or your preferred CSV editor.
+
+## Netzur Integration
+
+Netzur deployments expose subscriber and zone inventories via a REST endpoint secured with a Bearer token. Configure `/etc/lqos.conf` as follows:
+
+```ini
+[netzur_integration]
+enable_netzur = true
+api_key = "your-netzur-token"
+api_url = "https://netzur.example.com/api/libreqos"
+timeout_secs = 60
+use_mikrotik_ipv6 = false
+```
+
+- `enable_netzur` toggles automatic imports by `lqos_scheduler`.
+- `api_key` is the Bearer token generated inside Netzur.
+- `api_url` must return JSON containing `zones` (mapped to sites) and `customers` (mapped to client circuits and devices).
+- `timeout_secs` overrides the default HTTP timeout (60 seconds) when the API is slow.
+- `use_mikrotik_ipv6` enriches subscriber devices with IPv6 prefixes discovered via `mikrotikDHCPRouterList.csv`.
+
+Run a manual import with:
+
+```bash
+python3 integrationNetzur.py
+```
+
+The integration regenerates `ShapedDevices.csv` and, unless `always_overwrite_network_json` is disabled, updates `network.json`. Adjust the Integration → Common settings if you need to preserve an existing network map between Netzur syncs.
+
+## VISP Integration
+
+First, set the relevant parameters for VISP in `/etc/lqos.conf`:
+
+```ini
+[visp_integration]
+enable_visp = true
+client_id = "your-client-id"
+client_secret = "your-client-secret"
+username = "appuser-username"
+password = "appuser-password"
+# Optional: leave unset/blank to auto-select first ISP ID returned by token payload
+# isp_id = 0
+timeout_secs = 20
+# Optional: used for online session enrichment
+# online_users_domain = ""
+```
+
+Notes:
+- VISP import is GraphQL-based and currently defaults to a flat topology strategy.
+- The integration writes `ShapedDevices.csv` every run.
+- `network.json` is only overwritten when `always_overwrite_network_json = true` (under `[integration_common]`).
+- VISP auth tokens are cached in `/.visp_token_cache_*.json`.
+
+Run a manual import with:
+
+```bash
+python3 integrationVISP.py
+```
+
+To run automatically through `lqos_scheduler`, set:
+- `[visp_integration] enable_visp = true`
+- then restart scheduler:
+
+```bash
+sudo systemctl restart lqos_scheduler
+```
+
+## UISP Integration
+
+First, set the relevant parameters for UISP in `/etc/lqos.conf`.
+
+### Topology Strategies
+
+LibreQoS supports multiple topology strategies for UISP integration to balance CPU performance with network hierarchy needs:
+
+| Strategy | Description | CPU Impact | Use Case |
+|----------|-------------|------------|----------|
+| `flat` | Only shapes subscribers by service plan speed | Lowest | Maximum performance, simple subscriber-only shaping |
+| `ap_only` | Shapes by service plan and Access Point | Low | Good balance of performance and AP-level control |
+| `ap_site` | Shapes by service plan, Access Point, and Site | Medium | Site-level aggregation with moderate complexity |
+| `full` | Shapes entire network including backhauls, Sites, APs, and clients | Highest | **Recommended for most deployments**. Complete network hierarchy with backhaul awareness |
+
+**Choosing the Right Strategy:**
+- Use `full` for most deployments to get complete network topology awareness including backhaul links
+- Use `ap_site` if you need site-level control but don't need backhaul shaping
+- Use `ap_only` for better performance when site aggregation isn't needed
+- Use `flat` only when maximum performance is critical and you don't need any hierarchy
+
+**Performance Note:** When using `full` strategy with large networks, consider using the **promote_to_root** feature (see [Promote to Root Nodes](#promote-to-root-nodes-performance-optimization) above) to distribute CPU load across multiple cores.
+
+### Suspension Handling Strategies
+
+Configure how LibreQoS handles suspended customer accounts:
+
+| Strategy | Description | Use Case |
+|----------|-------------|----------|
+| `none` | Do not handle suspensions | When suspension handling is managed elsewhere |
+| `ignore` | Do not add suspended customers to network map | Reduces queue count and improves performance for networks with many suspended accounts |
+| `slow` | Limit suspended customers to 0.1 Mbps | Maintains minimal connectivity for suspended accounts (e.g., payment portals) |
+
+**Choosing a Suspension Strategy:**
+- Use `none` if your edge router or another system handles suspensions
+- Use `ignore` to reduce system load by not creating queues for suspended customers
+- Use `slow` to maintain minimal connectivity (useful for payment portals or service messages)
+
+### Burst
+
+- In UISP, Download Speed and Upload Speed are configured in Mbps (for example, 100 Mbps).
+- In UISP, Download Burst and Upload Burst are configured in kilobytes per second (kB/s).
+- Conversion and shaping:
+ - burst_mbps = kB/s × 8 / 1000
+ - Download Min = Download Speed (Mbps) × commit_bandwidth_multiplier
+ - Download Max = (Download Speed (Mbps) + burst_mbps) × bandwidth_overhead_factor
+ - Upload Min/Max are computed the same way from Upload Speed (Mbps) and Upload Burst (kB/s)
+- Example:
+ - UISP values: Download Speed = 100 Mbps, Download Burst = 12,500 kB/s
+ - Burst adds 12,500 × 8 / 1000 = 100 Mbps
+ - Download Min = 100 × commit_bandwidth_multiplier
+ - Download Max = (100 + 100) × bandwidth_overhead_factor
+- Quick reference (burst kB/s → added Mbps):
+ - 6,250 kB/s → +50 Mbps
+ - 12,500 kB/s → +100 Mbps
+ - 25,000 kB/s → +200 Mbps
+- Notes:
+ - Leave burst empty/null in UISP to disable burst.
+ - If suspended_strategy is set to slow, both Min and Max are set to 0.1 Mbps.
+
+### Configuration Example
+
+```ini
+[uisp_integration]
+# Core Settings
+enable_uisp = true
+token = "your-api-token-here"
+url = "https://uisp.your_domain.com"
+site = "Root_Site_Name" # Root site for topology perspective
+
+# Topology Strategy (see table above)
+strategy = "full" # Recommended for most deployments
+
+# Suspension Handling (see table above)
+suspended_strategy = "none"
+
+# Capacity Adjustments
+# UISP's reported AP capacities can be optimistic
+airmax_capacity = 0.65 # Use 65% of reported AirMax capacity
+ltu_capacity = 0.95 # Use 95% of reported LTU capacity
+
+# Site Management
+exclude_sites = [] # Sites to exclude, e.g., ["Test_Site", "Lab_Site"]
+use_ptmp_as_parent = true # For sites branched off PtMP Access Points
+
+# Bandwidth Adjustments
+bandwidth_overhead_factor = 1.15 # Give customers 15% above plan speed
+commit_bandwidth_multiplier = 0.98 # Set minimum to 98% of maximum (CIR)
+
+# Advanced Options
+ipv6_with_mikrotik = false # Enable if using DHCPv6 with MikroTik
+always_overwrite_network_json = false # Set true to rebuild topology each run
+exception_cpes = [] # CPE exceptions in ["cpe:parent"] format
+squash_sites = [] # Optional: sites to squash
+enable_squashing = false # Optional: enable AP/single-entry squashing logic
+do_not_squash_sites = [] # Optional: never squash these sites
+ignore_calculated_capacity = false # Optional: keep configured capacities even if calculated differs
+insecure_ssl = false # Optional: ignore UISP TLS certificate validation
+```
+
+### UISP Advanced/Operational Options
+
+The following UISP options are available in current builds and WebUI (Node Manager) config editors:
+
+- `exclude_sites`: list of site names to exclude from import.
+- `exception_cpes`: list of `cpe:parent` overrides for ambiguous parent assignment.
+- `squash_sites`: optional list of sites to squash in full strategy workflows.
+- `enable_squashing`: enables additional squashing behavior where supported.
+- `do_not_squash_sites`: explicit exclusions from squashing.
+- `use_ptmp_as_parent`: prefer PtMP AP as parent for relevant topology paths.
+- `ignore_calculated_capacity`: prefer configured capacities instead of integration-calculated values.
+- `insecure_ssl`: disables TLS certificate verification for UISP API calls.
+
+Recommended use:
+1. Keep `insecure_ssl = false` unless you have a known internal PKI/self-signed requirement.
+2. Use `exclude_sites` and `do_not_squash_sites` first for safer topology changes.
+3. Apply `squash_sites`/`enable_squashing` incrementally and validate queue placement after each change.
+
+To test the UISP Integration, use
+
+```shell
+cd /opt/libreqos/src
+sudo /opt/libreqos/src/bin/uisp_integration
+```
+
+On the first successful run, it will create a network.json and ShapedDevices.csv file.
+If a network.json file exists, it will not be overwritten, unless you set ```always_overwrite_network_json = true```.
+
+ShapedDevices.csv will be overwritten every time the UISP integration is run.
+
+To ensure the network.json is always overwritten with the newest version pulled in by the integration, please edit `/etc/lqos.conf` with the command `sudo nano /etc/lqos.conf`.
+Edit the file to set the value of `always_overwrite_network_json` to `true`.
+Then, run `sudo systemctl restart lqosd`.
+
+You have the option to run integrationUISP.py automatically on boot and every X minutes (set by the parameter `queue_refresh_interval_mins`), which is highly recommended. This can be enabled by setting ```enable_uisp = true``` in `/etc/lqos.conf`. Once set, run `sudo systemctl restart lqos_scheduler`.
+
+### UISP Overrides
+
+You can also modify the the following files to more accurately reflect your network:
+- integrationUISPbandwidths.csv
+- integrationUISProutes.csv
+
+Each of the files above have templates available in the `/opt/libreqos/src` folder. If you don't find them there, you can navigate [here](https://github.com/LibreQoE/LibreQoS/tree/develop/src). To utilize the template, copy the file (removing the `.template` part of the filename) and set the appropriate information inside each file.
+For example, if you want to change the set bandwidth for a site, you would do:
+```
+sudo cp /opt/libreqos/src/integrationUISPbandwidths.template.csv /opt/libreqos/src/integrationUISPbandwidths.csv
+```
+And edit the CSV using LibreOffice or your preferred CSV editor.
+
+#### UISP Route Overrides
+
+The default cost between nodes is typically 10. The integration creates a dot graph file `/opt/libreqos/src/graph.dot` which can be rendered using [Graphviz](https://dreampuf.github.io/GraphvizOnline/). This renders a map with the associated costs of all links.
+
+
+
+Say you have Site 1, Site 2, and Site 3.
+A backup path exists between Site 1 and Site 3, but is not the preferred path.
+Your preference is Site 1 > Site 2 > Site 3, but the integration by default connects Site 1 > Site 3 directly.
+
+To fix this, add a cost above the default for the path between Site 1 and Site 3.
+```
+Site 1, Site 3, 100
+Site 3, Site 1, 100
+```
+With this, data will flow Site 1 > Site 2 > Site 3.
+
+To make the change, perform a reload of the integration with ```sudo systemctl restart lqos_scheduler```.
+
+## WISPGate Integration
+
+First, set the relevant parameters for WISPGate in `/etc/lqos.conf`.
+There should be a section as follows:
+
+```
+[wispgate_integration]
+enable_wispgate = false
+wispgate_api_token = "token"
+wispgate_api_url = "https://your_wispgate_url.com"
+```
+
+If the section is missing, you can add it by copying the section above.
+Set the appropriate values for wispgate_api_token and wispgate_api_url, then save the file.
+
+To test the WISPGate Integration, use
+
+```shell
+python3 integrationWISPGate.py
+```
+
+On the first successful run, it will create a ShapedDevices.csv file and network.json.
+ShapedDevices.csv will be overwritten every time the WISPGate integration is run.
+
+To ensure the network.json is always overwritten with the newest version pulled in by the integration, please edit `/etc/lqos.conf` with the command `sudo nano /etc/lqos.conf`.
+Edit the file to set the value of `always_overwrite_network_json` to `true`.
+Then, run `sudo systemctl restart lqosd`.
+
+You have the option to run integrationWISPGate.py automatically on boot and every X minutes (set by the parameter `queue_refresh_interval_mins`), which is highly recommended. This can be enabled by setting ```enable_wispgate = true``` in `/etc/lqos.conf`.
+Once set, run `sudo systemctl restart lqos_scheduler`.
+
+## Powercode Integration
+
+First, set the relevant parameters for Powercode (powercode_api_key, powercode_api_url, etc.) in `/etc/lqos.conf`.
+
+To test the Powercode Integration, use
+
+```shell
+python3 integrationPowercode.py
+```
+
+On the first successful run, it will create a ShapedDevices.csv file.
+You can modify the network.json file manually to reflect Site/AP bandwidth limits.
+ShapedDevices.csv will be overwritten every time the Powercode integration is run.
+You have the option to run integrationPowercode.py automatically on boot and every X minutes (set by the parameter `queue_refresh_interval_mins`), which is highly recommended. This can be enabled by setting ```enable_powercode = true``` in `/etc/lqos.conf`.
+
+## Sonar Integration
+
+First, set the relevant parameters for Sonar (sonar_api_key, sonar_api_url, etc.) in `/etc/lqos.conf`.
+
+To test the Sonar Integration, use
+
+```shell
+python3 integrationSonar.py
+```
+
+On the first successful run, it will create a ShapedDevices.csv file.
+If a network.json file exists, it will not be overwritten, unless you set ```always_overwrite_network_json = true```.
+You can modify the network.json file to more accurately reflect bandwidth limits.
+ShapedDevices.csv will be overwritten every time the Sonar integration is run.
+You have the option to run integrationSonar.py automatically on boot and every X minutes (set by the parameter `queue_refresh_interval_mins`), which is highly recommended. This can be enabled by setting ```enable_sonar = true``` in `/etc/lqos.conf`.
+
+## Third-Party Tools
+
+### Jesync UI Tool Dashboard
+Jesync UI Tool Dashboard is a modern, web-based control panel designed to make managing LibreQoS and its integration files easier, faster, and more user-friendly.
+
+[https://github.com/jesienazareth/jesync_dashboard](https://github.com/jesienazareth/jesync_dashboard)
+
+### MikroTik PPPoE Integration
+This script automates the synchronization of MikroTik PPP secrets (e.g., PPPoE users) and active hotspot users with a LibreQoS-compatible CSV file (ShapedDevices.csv). It continuously monitors the MikroTik router for changes to PPP secrets and active hotspot users, such as additions, updates, or deletions, and updates the CSV file accordingly. The script also calculates rate limits (download/upload speeds) based on the assigned PPP profile and ensures the CSV file is always up-to-date.
+
+The script is designed to run as a background service using systemd, ensuring it starts automatically on boot and restarts in case of failures.
+
+[https://github.com/Kintoyyy/MikroTik-LibreQos-Integration](https://github.com/Kintoyyy/MikroTik-LibreQos-Integration)
diff --git a/_build/html/_sources/docs/v2.0/integrations-sonar.md.txt b/_build/html/_sources/docs/v2.0/integrations-sonar.md.txt
new file mode 100644
index 00000000..551ab363
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/integrations-sonar.md.txt
@@ -0,0 +1,22 @@
+# Sonar Integration
+
+First, set the relevant parameters for Sonar (sonar_api_key, sonar_api_url, etc.) in `/etc/lqos.conf`.
+
+To test the Sonar Integration, use
+
+```shell
+python3 integrationSonar.py
+```
+
+On the first successful run, it will create a ShapedDevices.csv file.
+If a network.json file exists, it will not be overwritten, unless you set ```always_overwrite_network_json = true```.
+You can modify the network.json file to more accurately reflect bandwidth limits.
+ShapedDevices.csv will be overwritten every time the Sonar integration is run.
+You have the option to run integrationSonar.py automatically on boot and every X minutes (set by the parameter `queue_refresh_interval_mins`), which is highly recommended. This can be enabled by setting ```enable_sonar = true``` in `/etc/lqos.conf`.
+
+
+## Related Pages
+
+- [CRM/NMS Integrations](integrations.md)
+- [Operating Modes and Source of Truth](operating-modes.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/_build/html/_sources/docs/v2.0/integrations-splynx.md.txt b/_build/html/_sources/docs/v2.0/integrations-splynx.md.txt
new file mode 100644
index 00000000..ea6248bb
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/integrations-splynx.md.txt
@@ -0,0 +1,116 @@
+# Splynx Integration
+
+> **⚠️ Breaking Change Notice**: Prior to v1.5-RC-2, the default Splynx strategy was `full`. Starting with v1.5-RC-2, the default strategy is `ap_only` for improved CPU performance. If you require the previous behavior, explicitly set `strategy = "full"` in your Splynx configuration section.
+
+First, set the relevant parameters for Splynx (splynx_api_key, splynx_api_secret, etc.) in `/etc/lqos.conf`.
+
+### Topology Strategies
+
+LibreQoS supports multiple topology strategies for Splynx integration to balance CPU performance with network hierarchy needs:
+
+| Strategy | Description | CPU Impact | Use Case |
+|----------|-------------|------------|----------|
+| `flat` | Only shapes subscribers, no hierarchy | Lowest | Maximum performance, simple subscriber-only shaping |
+| `ap_only` | Single layer: AP → Clients | Low | **Default**. Best balance of performance and structure |
+| `ap_site` | Two layers: Site → AP → Clients | Medium | Site-level aggregation with moderate complexity |
+| `full` | Complete topology mapping | Highest | Full network hierarchy representation |
+
+Configure the strategy in `/etc/lqos.conf` under the `[splynx_integration]` section:
+
+```ini
+[splynx_integration]
+# ... other splynx settings ...
+strategy = "ap_only"
+```
+
+**Performance Considerations:**
+- `flat` and `ap_only` strategies significantly reduce CPU load by limiting network depth
+- Choose `ap_only` for most deployments unless you need site-level traffic aggregation
+- Only use `full` if you require complete network topology representation and have adequate CPU resources
+
+### Promote to Root Nodes (Performance Optimization)
+
+When using `full` topology strategy, you may encounter CPU performance bottlenecks where all traffic flows through a single root site, limiting throughput to what one CPU core can handle.
+
+The **promote_to_root** feature solves this by promoting specific sites to root-level nodes, distributing traffic shaping across multiple CPU cores.
+
+**Configuration:**
+1. Navigate to Integration → Common in the WebUI
+2. In the "Promote to Root Nodes" field, enter one site name per line:
+```
+Remote_Site_Alpha
+Remote_Site_Beta
+Datacenter_West
+```
+
+**Benefits:**
+- Eliminates single-CPU bottleneck for networks with remote sites
+- Distributes traffic shaping across multiple CPU cores
+- Improves overall network performance for large topologies
+- Works with both Splynx and UISP integrations
+
+**When to Use:**
+- Networks with multiple high-capacity remote sites
+- When using `full` topology strategy and experiencing CPU limitations
+- Large networks where root site traffic exceeds single-core capacity
+
+### Splynx API Access
+
+The Splynx Integration uses Basic authentication. For using this type of authentication, please make sure you enable [Unsecure access](https://splynx.docs.apiary.io/#introduction/authentication) in your Splynx API key settings. Also the Splynx API key should be granted access to the necessary permissions.
+
+| Category | Name | Permission |
+|----------------|------------------------------|------------|
+| Tariff Plans | Internet | View |
+| FUP | Compiler | View |
+| FUP | Policies | View |
+| FUP | Capped Data | View |
+| FUP | CAP Tariff | View |
+| FUP | FUP Limits | View |
+| Customers | Customer | View |
+| Customers | Customers Online | View |
+| Customers | Customer Internet services | View |
+| Networking | Routers | View |
+| Networking | Router contention | View |
+| Networking | MikroTik | View |
+| Networking | Monitoring | View |
+| Networking | Network Sites | View |
+| Networking | IPv4 Networks | View |
+| Networking | IPv4 Networks IP | View |
+| Networking | CPE | View |
+| Networking | CPE AP | View |
+| Networking | IPv6 Networks | View |
+| Networking | IPv6 Networks IP (Addresses) | View |
+| Administration | Locations | View |
+
+To test the Splynx Integration, use
+
+```shell
+python3 integrationSplynx.py
+```
+
+On the first successful run, it will create a ShapedDevices.csv file and network.json.
+ShapedDevices.csv will be overwritten every time the Splynx integration is run.
+
+To ensure the network.json is always overwritten with the newest version pulled in by the integration, please edit `/etc/lqos.conf` with the command `sudo nano /etc/lqos.conf`.
+Edit the file to set the value of `always_overwrite_network_json` to `true`.
+Then, run `sudo systemctl restart lqosd`.
+
+You have the option to run integrationSplynx.py automatically on boot and every X minutes (set by the parameter `queue_refresh_interval_mins`), which is highly recommended. This can be enabled by setting ```enable_splynx = true``` under the ```[splynx_integration]``` section in `/etc/lqos.conf`.
+Once set, run `sudo systemctl restart lqos_scheduler`.
+
+### Splynx Overrides
+
+You can also modify the the file `integrationSplynxBandwidths.csv` to override the default bandwidths for each Node (Site, AP).
+
+A template is available in the `/opt/libreqos/src` folder. To utilize the template, copy the file `integrationSplynxBandwidths.template.csv` (removing the `.template` part of the filename) and set the appropriate information inside each file. For example, if you want to change the set bandwidth for a site, you would do:
+```
+sudo cp /opt/libreqos/src/integrationSplynxBandwidths.template.csv /opt/libreqos/src/integrationSplynxBandwidths.csv
+```
+And edit the CSV using LibreOffice or your preferred CSV editor.
+
+
+## Related Pages
+
+- [CRM/NMS Integrations](integrations.md)
+- [Operating Modes and Source of Truth](operating-modes.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/_build/html/_sources/docs/v2.0/integrations-uisp.md.txt b/_build/html/_sources/docs/v2.0/integrations-uisp.md.txt
new file mode 100644
index 00000000..dfdd0f96
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/integrations-uisp.md.txt
@@ -0,0 +1,195 @@
+# UISP Integration
+
+First, set the relevant parameters for UISP in `/etc/lqos.conf`.
+
+### Topology Strategies
+
+LibreQoS supports multiple topology strategies for UISP integration to balance CPU performance with network hierarchy needs:
+
+| Strategy | Description | CPU Impact | Use Case |
+|----------|-------------|------------|----------|
+| `flat` | Only shapes subscribers by service plan speed | Lowest | Maximum performance, simple subscriber-only shaping |
+| `ap_only` | Shapes by service plan and Access Point | Low | Good balance of performance and AP-level control |
+| `ap_site` | Shapes by service plan, Access Point, and Site | Medium | Site-level aggregation with moderate complexity |
+| `full` | Shapes entire network including backhauls, Sites, APs, and clients | Highest | **Recommended for most deployments**. Complete network hierarchy with backhaul awareness |
+
+**Choosing the Right Strategy:**
+- Use `full` for most deployments to get complete network topology awareness including backhaul links
+- Use `ap_site` if you need site-level control but don't need backhaul shaping
+- Use `ap_only` for better performance when site aggregation isn't needed
+- Use `flat` only when maximum performance is critical and you don't need any hierarchy
+
+**Performance Note:** When using `full` strategy with large networks, consider using `promote_to_root` to distribute CPU load across multiple cores.
+
+### Promote to Root Nodes (Performance Optimization)
+
+When using `full` topology strategy, traffic can bottleneck on a single root node/CPU core.
+
+The `promote_to_root` feature can reduce this by promoting selected sites to root-level nodes so load is distributed.
+
+Configuration:
+1. Navigate to `Configuration -> Integrations` in WebUI.
+2. In `Promote to Root Nodes`, enter one site per line.
+
+Example:
+```
+Remote_Site_Alpha
+Remote_Site_Beta
+Datacenter_West
+```
+
+When to use:
+- Multi-site networks with high-capacity remote sites.
+- `full` strategy deployments showing single-core saturation.
+
+### Suspension Handling Strategies
+
+Configure how LibreQoS handles suspended customer accounts:
+
+| Strategy | Description | Use Case |
+|----------|-------------|----------|
+| `none` | Do not handle suspensions | When suspension handling is managed elsewhere |
+| `ignore` | Do not add suspended customers to network map | Reduces queue count and improves performance for networks with many suspended accounts |
+| `slow` | Limit suspended customers to 0.1 Mbps | Maintains minimal connectivity for suspended accounts (e.g., payment portals) |
+
+**Choosing a Suspension Strategy:**
+- Use `none` if your edge router or another system handles suspensions
+- Use `ignore` to reduce system load by not creating queues for suspended customers
+- Use `slow` to maintain minimal connectivity (useful for payment portals or service messages)
+
+### Burst
+
+- In UISP, Download Speed and Upload Speed are configured in Mbps (for example, 100 Mbps).
+- In UISP, Download Burst and Upload Burst are configured in kilobytes per second (kB/s).
+- Conversion and shaping:
+ - burst_mbps = kB/s × 8 / 1000
+ - Download Min = Download Speed (Mbps) × commit_bandwidth_multiplier
+ - Download Max = (Download Speed (Mbps) + burst_mbps) × bandwidth_overhead_factor
+ - Upload Min/Max are computed the same way from Upload Speed (Mbps) and Upload Burst (kB/s)
+- Example:
+ - UISP values: Download Speed = 100 Mbps, Download Burst = 12,500 kB/s
+ - Burst adds 12,500 × 8 / 1000 = 100 Mbps
+ - Download Min = 100 × commit_bandwidth_multiplier
+ - Download Max = (100 + 100) × bandwidth_overhead_factor
+- Quick reference (burst kB/s → added Mbps):
+ - 6,250 kB/s → +50 Mbps
+ - 12,500 kB/s → +100 Mbps
+ - 25,000 kB/s → +200 Mbps
+- Notes:
+ - Leave burst empty/null in UISP to disable burst.
+ - If suspended_strategy is set to slow, both Min and Max are set to 0.1 Mbps.
+
+### Configuration Example
+
+```ini
+[uisp_integration]
+# Core Settings
+enable_uisp = true
+token = "your-api-token-here"
+url = "https://uisp.your_domain.com"
+site = "Root_Site_Name" # Root site for topology perspective
+
+# Topology Strategy (see table above)
+strategy = "full" # Recommended for most deployments
+
+# Suspension Handling (see table above)
+suspended_strategy = "none"
+
+# Capacity Adjustments
+# UISP's reported AP capacities can be optimistic
+airmax_capacity = 0.65 # Use 65% of reported AirMax capacity
+ltu_capacity = 0.95 # Use 95% of reported LTU capacity
+
+# Site Management
+exclude_sites = [] # Sites to exclude, e.g., ["Test_Site", "Lab_Site"]
+use_ptmp_as_parent = true # For sites branched off PtMP Access Points
+
+# Bandwidth Adjustments
+bandwidth_overhead_factor = 1.15 # Give customers 15% above plan speed
+commit_bandwidth_multiplier = 0.98 # Set minimum to 98% of maximum (CIR)
+
+# Advanced Options
+ipv6_with_mikrotik = false # Enable if using DHCPv6 with MikroTik
+always_overwrite_network_json = false # Set true to rebuild topology each run
+exception_cpes = [] # CPE exceptions in ["cpe:parent"] format
+squash_sites = [] # Optional: sites to squash
+enable_squashing = false # Optional: enable AP/single-entry squashing logic
+do_not_squash_sites = [] # Optional: never squash these sites
+ignore_calculated_capacity = false # Optional: keep configured capacities even if calculated differs
+insecure_ssl = false # Optional: ignore UISP TLS certificate validation
+```
+
+### UISP Advanced/Operational Options
+
+The following UISP options are available in current builds and WebUI (Node Manager) config editors:
+
+- `exclude_sites`: list of site names to exclude from import.
+- `exception_cpes`: list of `cpe:parent` overrides for ambiguous parent assignment.
+- `squash_sites`: optional list of sites to squash in full strategy workflows.
+- `enable_squashing`: enables additional squashing behavior where supported.
+- `do_not_squash_sites`: explicit exclusions from squashing.
+- `use_ptmp_as_parent`: prefer PtMP AP as parent for relevant topology paths.
+- `ignore_calculated_capacity`: prefer configured capacities instead of integration-calculated values.
+- `insecure_ssl`: disables TLS certificate verification for UISP API calls.
+
+Recommended use:
+1. Keep `insecure_ssl = false` unless you have a known internal PKI/self-signed requirement.
+2. Use `exclude_sites` and `do_not_squash_sites` first for safer topology changes.
+3. Apply `squash_sites`/`enable_squashing` incrementally and validate queue placement after each change.
+
+To test the UISP Integration, use
+
+```shell
+cd /opt/libreqos/src
+sudo /opt/libreqos/src/bin/uisp_integration
+```
+
+On the first successful run, it will create a network.json and ShapedDevices.csv file.
+If a network.json file exists, it will not be overwritten, unless you set ```always_overwrite_network_json = true```.
+
+ShapedDevices.csv will be overwritten every time the UISP integration is run.
+
+To ensure the network.json is always overwritten with the newest version pulled in by the integration, please edit `/etc/lqos.conf` with the command `sudo nano /etc/lqos.conf`.
+Edit the file to set the value of `always_overwrite_network_json` to `true`.
+Then, run `sudo systemctl restart lqosd`.
+
+You have the option to run integrationUISP.py automatically on boot and every X minutes (set by the parameter `queue_refresh_interval_mins`), which is highly recommended. This can be enabled by setting ```enable_uisp = true``` in `/etc/lqos.conf`. Once set, run `sudo systemctl restart lqos_scheduler`.
+
+### UISP Overrides
+
+You can also modify the the following files to more accurately reflect your network:
+- integrationUISPbandwidths.csv
+- integrationUISProutes.csv
+
+Each of the files above have templates available in the `/opt/libreqos/src` folder. If you don't find them there, you can navigate [here](https://github.com/LibreQoE/LibreQoS/tree/develop/src). To utilize the template, copy the file (removing the `.template` part of the filename) and set the appropriate information inside each file.
+For example, if you want to change the set bandwidth for a site, you would do:
+```
+sudo cp /opt/libreqos/src/integrationUISPbandwidths.template.csv /opt/libreqos/src/integrationUISPbandwidths.csv
+```
+And edit the CSV using LibreOffice or your preferred CSV editor.
+
+#### UISP Route Overrides
+
+The default cost between nodes is typically 10. The integration creates a dot graph file `/opt/libreqos/src/graph.dot` which can be rendered using [Graphviz](https://dreampuf.github.io/GraphvizOnline/). This renders a map with the associated costs of all links.
+
+
+
+Say you have Site 1, Site 2, and Site 3.
+A backup path exists between Site 1 and Site 3, but is not the preferred path.
+Your preference is Site 1 > Site 2 > Site 3, but the integration by default connects Site 1 > Site 3 directly.
+
+To fix this, add a cost above the default for the path between Site 1 and Site 3.
+```
+Site 1, Site 3, 100
+Site 3, Site 1, 100
+```
+With this, data will flow Site 1 > Site 2 > Site 3.
+
+To make the change, perform a reload of the integration with ```sudo systemctl restart lqos_scheduler```.
+
+
+## Related Pages
+
+- [CRM/NMS Integrations](integrations.md)
+- [Operating Modes and Source of Truth](operating-modes.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/_build/html/_sources/docs/v2.0/integrations-visp.md.txt b/_build/html/_sources/docs/v2.0/integrations-visp.md.txt
new file mode 100644
index 00000000..0287d787
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/integrations-visp.md.txt
@@ -0,0 +1,44 @@
+# VISP Integration
+
+First, set the relevant parameters for VISP in `/etc/lqos.conf`:
+
+```ini
+[visp_integration]
+enable_visp = true
+client_id = "your-client-id"
+client_secret = "your-client-secret"
+username = "appuser-username"
+password = "appuser-password"
+# Optional: leave unset/blank to auto-select first ISP ID returned by token payload
+# isp_id = 0
+timeout_secs = 20
+# Optional: used for online session enrichment
+# online_users_domain = ""
+```
+
+Notes:
+- VISP import is GraphQL-based and currently defaults to a flat topology strategy.
+- The integration writes `ShapedDevices.csv` every run.
+- `network.json` is only overwritten when `always_overwrite_network_json = true` (under `[integration_common]`).
+- VISP auth tokens are cached in `/.visp_token_cache_*.json`.
+
+Run a manual import with:
+
+```bash
+python3 integrationVISP.py
+```
+
+To run automatically through `lqos_scheduler`, set:
+- `[visp_integration] enable_visp = true`
+- then restart scheduler:
+
+```bash
+sudo systemctl restart lqos_scheduler
+```
+
+
+## Related Pages
+
+- [CRM/NMS Integrations](integrations.md)
+- [Operating Modes and Source of Truth](operating-modes.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/_build/html/_sources/docs/v2.0/integrations-wispgate.md.txt b/_build/html/_sources/docs/v2.0/integrations-wispgate.md.txt
new file mode 100644
index 00000000..fae22085
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/integrations-wispgate.md.txt
@@ -0,0 +1,37 @@
+# WISPGate Integration
+
+First, set the relevant parameters for WISPGate in `/etc/lqos.conf`.
+There should be a section as follows:
+
+```
+[wispgate_integration]
+enable_wispgate = false
+wispgate_api_token = "token"
+wispgate_api_url = "https://your_wispgate_url.com"
+```
+
+If the section is missing, you can add it by copying the section above.
+Set the appropriate values for wispgate_api_token and wispgate_api_url, then save the file.
+
+To test the WISPGate Integration, use
+
+```shell
+python3 integrationWISPGate.py
+```
+
+On the first successful run, it will create a ShapedDevices.csv file and network.json.
+ShapedDevices.csv will be overwritten every time the WISPGate integration is run.
+
+To ensure the network.json is always overwritten with the newest version pulled in by the integration, please edit `/etc/lqos.conf` with the command `sudo nano /etc/lqos.conf`.
+Edit the file to set the value of `always_overwrite_network_json` to `true`.
+Then, run `sudo systemctl restart lqosd`.
+
+You have the option to run integrationWISPGate.py automatically on boot and every X minutes (set by the parameter `queue_refresh_interval_mins`), which is highly recommended. This can be enabled by setting ```enable_wispgate = true``` in `/etc/lqos.conf`.
+Once set, run `sudo systemctl restart lqos_scheduler`.
+
+
+## Related Pages
+
+- [CRM/NMS Integrations](integrations.md)
+- [Operating Modes and Source of Truth](operating-modes.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/_build/html/_sources/docs/v2.0/integrations.md.txt b/_build/html/_sources/docs/v2.0/integrations.md.txt
new file mode 100644
index 00000000..7ed9df2c
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/integrations.md.txt
@@ -0,0 +1,57 @@
+# CRM/NMS Integrations
+
+## Page Purpose
+
+Use this page to choose and configure supported CRM/NMS integrations. Use per-integration pages for specific setup details.
+
+Most operators use built-in integrations. If you use your own scripts as the source of truth for `network.json` and `ShapedDevices.csv`, start with [Operating Modes and Source of Truth](operating-modes.md).
+
+```{mermaid}
+flowchart LR
+ A[CRM/NMS] --> B[LibreQoS Integration Job]
+ B --> C[ShapedDevices.csv]
+ B --> D[network.json]
+ C --> E[lqos_scheduler]
+ D --> E
+ E --> F[Shaping Updates]
+ E --> G[WebUI Status / Urgent Issues]
+```
+
+## Choose Your Integration Path
+
+| Path | Best fit | Primary source of truth |
+|---|---|---|
+| Built-in integration | Most operators using supported systems | CRM/NMS via LibreQoS integration jobs |
+| Custom source-of-truth | Operators with in-house CRM/NMS sync logic | External generated files (`network.json`, `ShapedDevices.csv`) |
+
+## Where in WebUI
+
+- Integration defaults/common behavior: `Configuration -> Integrations`
+- Per-integration configuration fields: `Configuration -> Integrations`
+- Operational health checks after sync changes: `WebUI -> Scheduler Status` and `WebUI -> Urgent Issues`
+- Topology/result validation: `WebUI -> Network Tree Overview` and `Flow Map`
+
+## Built-In Integrations
+
+- [Splynx Integration](integrations-splynx.md)
+- [UISP Integration](integrations-uisp.md)
+- [Netzur Integration](integrations-netzur.md)
+- [VISP Integration](integrations-visp.md)
+- [WISPGate Integration](integrations-wispgate.md)
+- [Powercode Integration](integrations-powercode.md)
+- [Sonar Integration](integrations-sonar.md)
+
+## Important Overwrite Behavior
+
+When integrations are enabled:
+- `ShapedDevices.csv` is typically regenerated by integration sync jobs.
+- `network.json` may also be overwritten depending on integration settings (for example `always_overwrite_network_json`).
+- Manual edits may be overwritten on the next refresh cycle.
+
+## Related Pages
+
+- [Quickstart](quickstart.md)
+- [Operating Modes and Source of Truth](operating-modes.md)
+- [Configure LibreQoS](configuration.md)
+- [Scale Planning and Topology Design](scale-topology.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/_build/html/_sources/docs/v2.0/node-manager-ui.md.txt b/_build/html/_sources/docs/v2.0/node-manager-ui.md.txt
new file mode 100644
index 00000000..32dbcf00
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/node-manager-ui.md.txt
@@ -0,0 +1,72 @@
+# LibreQoS WebUI (Node Manager)
+
+This page documents key WebUI (Node Manager) views and operational behavior in the local WebUI (`http://your_shaper_ip:9123`).
+
+## Core Views
+
+### Dashboard
+- Widget-based overview of throughput, retransmits, RTT, flow counts, and queue activity.
+- Dashboard content can vary by version and enabled features.
+
+### Network Tree Overview
+- Hierarchical topology view of nodes/circuits from the shaper perspective.
+- Useful for spotting bottlenecks and parent/child utilization patterns.
+
+### Flow Map
+- Geographic flow visualization based on endpoint geolocation.
+- Best used when enough recent flow data is available.
+
+### ASN Explorer
+- ASN-centric traffic exploration (volume, RTT/retransmit context, and related flow details).
+- Empty results often indicate low recent data volume rather than failure.
+
+### CPU Tree / CPU Weights
+- Shows queue/circuit distribution by CPU core.
+- Helps evaluate binpacking and load distribution behavior.
+
+### Shaped Devices Editor
+- CRUD editor for `ShapedDevices.csv`.
+- Supports paging and filtering in current builds.
+
+### Urgent Issues
+- WebUI can display urgent operational issues generated by backend services.
+- Examples include mapping/license-limit warnings and other high-priority health events.
+- Operators can acknowledge/clear issues in the UI after review.
+- Common codes include `MAPPED_CIRCUIT_LIMIT` and `TC_U16_OVERFLOW` (see [Troubleshooting](troubleshooting.md#urgent-issue-codes-and-first-actions)).
+
+### Scheduler Status
+- WebUI surfaces scheduler health/readiness.
+- Use it to quickly verify periodic refresh operation after config/integration changes.
+- If status indicates errors, correlate with:
+ - `journalctl -u lqos_scheduler --since "30 minutes ago"`
+ - `journalctl -u lqosd --since "30 minutes ago"`
+
+## Privacy / Redaction Mode
+
+- Toggle with the mask icon in the top navigation.
+- Redaction is client-side and stored in browser local storage.
+- Redaction helps hide PII in screenshots/demos.
+- Redaction does not modify `ShapedDevices.csv`, `network.json`, or any backend data.
+
+## Common Empty-State Behavior
+
+The following pages may appear sparse/blank when data is low:
+- Flow Map
+- Tree Overview Sankey views
+- ASN Explorer
+
+When this happens:
+1. Confirm `lqosd` is healthy.
+2. Wait for fresh traffic data.
+3. Reload the page.
+4. Check logs:
+
+```bash
+journalctl -u lqosd --since "10 minutes ago"
+```
+
+## Useful Related Pages
+
+- [Components](components.md)
+- [Configuration](configuration.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/_build/html/_sources/docs/v2.0/operating-modes.md.txt b/_build/html/_sources/docs/v2.0/operating-modes.md.txt
new file mode 100644
index 00000000..fd61ae85
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/operating-modes.md.txt
@@ -0,0 +1,51 @@
+# Operating Modes and Source of Truth
+
+## Page Purpose
+
+Use this page to choose and enforce your source-of-truth policy (built-in integrations vs custom source-of-truth) before production changes.
+
+```{mermaid}
+flowchart TD
+ A[Choose Source of Truth] --> B{Using built-in CRM/NMS integration?}
+ B -->|Yes| C[Built-in Integrations Mode]
+ B -->|No| D{Generating files from your own scripts/systems?}
+ D -->|Yes| E[Custom Source-of-Truth Mode]
+ D -->|No| F[Manual Files Mode]
+ C --> G[Integration sync jobs own file refresh]
+ E --> H[External script pipeline owns persistence]
+ F --> I[Direct file maintenance; best for small networks]
+```
+
+LibreQoS supports two first-class operating modes.
+
+## Built-in Integrations (Recommended for Most Operators)
+
+In this mode, your CRM/NMS is the source of truth and LibreQoS integration jobs produce shaping inputs.
+
+Key behavior:
+- `ShapedDevices.csv` is regenerated by integration sync cycles.
+- `network.json` overwrite behavior depends on integration settings (for example `always_overwrite_network_json`).
+- Direct manual edits may be overwritten on the next scheduler refresh.
+
+## Custom Source-of-Truth
+
+In this mode, your own scripts/systems generate `network.json` and `ShapedDevices.csv`.
+
+Key behavior:
+- Your external workflow owns persistence.
+- WebUI edits are valid for quick operational changes.
+- Permanent changes should be made in your external source-of-truth workflow.
+
+## Mode Declaration Checklist (Before Go-Live)
+
+1. Pick one primary source of truth.
+2. Confirm which system can write production shaping inputs.
+3. Confirm scheduler refresh behavior and overwrite cadence.
+4. Document your hotfix workflow (WebUI, external editor, or both).
+5. Do not maintain competing edits in multiple systems for the same objects.
+
+## Related Pages
+
+- [Configure LibreQoS](configuration.md)
+- [CRM/NMS Integrations](integrations.md)
+- [Advanced Configuration Reference](configuration-advanced.md)
diff --git a/_build/html/_sources/docs/v2.0/performance-tuning.md.txt b/_build/html/_sources/docs/v2.0/performance-tuning.md.txt
new file mode 100644
index 00000000..7d676209
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/performance-tuning.md.txt
@@ -0,0 +1,76 @@
+# Performance Tuning
+
+## CPU and IRQ Baseline
+
+Set CPU frequency governor to performance on bare metal/hypervisor hosts:
+
+```bash
+sudo cpupower frequency-set --governor performance
+```
+
+Confirm NIC queue count and CPU distribution are sensible for your hardware:
+
+```bash
+ethtool -l
+grep -E 'CPU\\(|IRQ' /proc/interrupts | head -n 50
+```
+
+If a single queue/CPU is saturated while others are idle, rebalance queue/IRQ affinity and revisit queue-count settings in `/etc/lqos.conf`.
+
+## Topology/Queue Pressure
+
+When shaping large hierarchies:
+
+- Prefer lower-depth integration strategies (`ap_only`/`ap_site`) unless full hierarchy is required.
+- Use `promote_to_root` for large multi-site topologies to avoid single-core choke points.
+- Validate WebUI CPU Tree/CPU Weights after major topology changes.
+
+## Scheduler Refresh and Load
+
+`lqos_scheduler` refresh cadence affects control-plane load and change responsiveness.
+
+- Start with a conservative `queue_refresh_interval_mins`.
+- Decrease interval only if your integration/API and host can handle the extra churn.
+- After changing interval, monitor:
+ - `journalctl -u lqos_scheduler --since "30 minutes ago"`
+ - WebUI scheduler status
+
+## StormGuard Rollout
+
+If using StormGuard:
+
+1. Start with `dry_run = true`.
+2. Observe at least one busy period.
+3. Move to live mode only after reviewing debug/status behavior.
+
+See [StormGuard](stormguard.md) for details.
+
+## Startup/Boot Delays
+
+If Ubuntu startup is slow due to network-online dependencies, inspect target dependencies:
+
+```bash
+systemctl show -p WantedBy network-online.target
+```
+
+On some Ubuntu installs, disabling unused cloud/iSCSI services may help:
+
+```bash
+sudo systemctl disable cloud-config iscsid cloud-final
+```
+
+Validate this against your environment before disabling services.
+
+## Routing Convergence (OSPF)
+
+For routed deployments, tune OSPF neighbor timers on core and edge routers to reduce outage windows during reboots:
+
+- hello interval
+- dead interval
+
+## Related Optimization and Resilience Pages
+
+- [Scale Planning and Topology Design](scale-topology.md)
+- [StormGuard](stormguard.md)
+- [High Availability and Failure Domains](high-availability.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/_build/html/_sources/docs/v2.0/prereq.md.txt b/_build/html/_sources/docs/v2.0/prereq.md.txt
new file mode 100644
index 00000000..606b222d
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/prereq.md.txt
@@ -0,0 +1,33 @@
+# Prerequisites
+
+## Servers & Hypervisors
+
+### Disable Hyper-Threading in the BIOS
+Disable hyperthreading on the BIOS/UEFI of your host system. Hyperthreaading is also known as Simultaneous Multi Threading (SMT) on AMD systems. Disabling this is very important for optimal performance of the XDP cpumap filtering and, in turn, throughput and latency.
+
+- Boot, pressing the appropriate key to enter the BIOS settings
+- For AMD systems, you will have to navigate the settings to find the "SMT Control" setting. Usually it is under something like ```Advanced -> AMD CBS -> CPU Common Options -> Thread Enablement -> SMT Control``` Once you find it, switch to "Disabled" or "Off"
+- For Intel systems, you will also have to navigate the settings to find the "hyperthrading" toggle option. On HP servers it's under ```System Configuration > BIOS/Platform Configuration (RBSU) > Processor Options > Intel (R) Hyperthreading Options.```
+- Save changes and reboot
+
+### Disable SR-IOV in the BIOS
+
+SR-IOV can disable XDP native (driver mode) on Physical Functions (PFs), forcing XDP Generic (SKB) and reducing performance and stability for LibreQoS. Disable SR-IOV in BIOS/UEFI for NICs used by LibreQoS. If per-slot/per-port options exist, set them to Disabled.
+
+## Hypervisors
+
+### Proxmox
+
+For Proxmox VMs, NIC passthrough is required to achieve throughput above 10 Gbps (XDP vs generic XDP).
+
+LibreQoS requires 2 or more RX/TX queues, so when using Proxmox, please be sure to enable [Multiqueue](https://forum.proxmox.com/threads/where-is-multiqueue.146783/) for the shaping interfaces assigned to the VM. Multiqueue should be set equal to the number of vCPU cores assigned to the VM.
+
+### Hyper-V
+
+#### Hyper-V MAC Spoofing (If Inside a VM)
+
+If your LibreQoS system is running inside Hyper-V and you’ve bridged two vNICs (eth1, eth2) — Hyper-V will block traffic from the bridge because the bridge generates frames with different MACs than the vNIC’s assigned MAC. To fix this on a Windows host:
+```
+Set-VMNetworkAdapter -VMName "YourLinuxVM" -MacAddressSpoofing On
+```
+Then restart the VM.
diff --git a/_build/html/_sources/docs/v2.0/quickstart.md.txt b/_build/html/_sources/docs/v2.0/quickstart.md.txt
new file mode 100644
index 00000000..61cd05cf
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/quickstart.md.txt
@@ -0,0 +1,143 @@
+# Quickstart: Choose Your Deployment Path
+
+Use this page to choose the correct deployment path quickly, then execute only the steps for that path.
+
+```{mermaid}
+flowchart TD
+ A[Start Here: Quickstart] --> B{Choose Path}
+ B --> C[Testbed / Lab]
+ B --> D[Supported Integration]
+ B --> E[Custom Script Integration]
+ B --> F[Manual Files <100 subscribers]
+ C --> G[Configure + Validate in WebUI]
+ D --> G
+ E --> G
+ F --> G
+ G --> H[Troubleshoot / Optimize / Scale]
+```
+
+## Common Install Foundation
+
+Complete this once before any path-specific steps.
+
+```{mermaid}
+flowchart LR
+ A[Review Design + Requirements] --> B[Host Prerequisites + Ubuntu]
+ B --> C[Configure Bridge]
+ C --> D[Install LibreQoS .deb]
+ D --> E[Open WebUI]
+```
+
+1. Review deployment assumptions and capacity:
+ - [Deployment Scenarios](design.md)
+ - [System Requirements](requirements.md)
+2. Prepare host and OS:
+ - [Server Setup - Prerequisites](prereq.md)
+ - [Install Ubuntu Server 24.04](ubuntu-server.md)
+3. Configure bridge mode:
+ - [Configure Shaping Bridge](bridge.md)
+4. Install LibreQoS (`.deb` recommended):
+
+```bash
+cd ~
+sudo apt-get update
+sudo apt-get upgrade
+wget https://download.libreqos.com/{deb_url_v1_5}
+sudo apt install ./{deb_url_v1_5}
+```
+
+5. Open WebUI at `http://your_shaper_ip:9123`.
+
+## Testbed / Lab
+
+### When to choose
+
+You want to validate behavior in a controlled environment before inline production.
+
+### Do this now
+
+1. Build a lab topology (LibreQoS + traffic generator endpoints + optional OSPF/BGP path simulation).
+2. Choose a lab track:
+ - **Lab with manual files**: validate `network.json` + `ShapedDevices.csv` behavior.
+ - **Lab with supported integration**: validate imported subscriber/topology data.
+3. Generate traffic and validate in WebUI (Dashboard, Tree, Flow, Scheduler Status, Urgent Issues).
+4. Confirm expected shaping behavior and stability.
+
+### Then go here
+
+- [Configure LibreQoS](configuration.md)
+- [Operating Modes and Source of Truth](operating-modes.md)
+- [CRM/NMS Integrations](integrations.md)
+- [Troubleshooting](troubleshooting.md)
+
+## Supported Integration
+
+### When to choose
+
+Your CRM/NMS is supported by built-in LibreQoS integrations.
+
+### Do this now
+
+1. Configure integration settings in WebUI.
+2. Run initial sync and validate imported shaping/topology data.
+3. Place LibreQoS inline for pilot traffic.
+4. Validate WebUI health signals (Scheduler Status, Urgent Issues, topology/flow views).
+5. Expand pilot scope after stable operation.
+
+Note:
+- In integration mode, `ShapedDevices.csv` is typically regenerated by sync jobs.
+- `network.json` overwrite behavior depends on integration settings (for example `always_overwrite_network_json`).
+
+### Then go here
+
+- [CRM/NMS Integrations](integrations.md)
+- [Scale Planning and Topology Design](scale-topology.md)
+- [Troubleshooting](troubleshooting.md)
+
+## Custom Script Integration
+
+### When to choose
+
+Your CRM/NMS is unsupported and you will generate `network.json` + `ShapedDevices.csv` with your own pipeline.
+
+### Do this now
+
+1. Implement script/process to generate and refresh shaping files.
+2. Declare your script outputs as source-of-truth.
+3. Place LibreQoS inline for pilot traffic.
+4. Use WebUI for operational checks and quick adjustments.
+5. Move permanent changes back into your script workflow.
+
+Note:
+- WebUI edits are useful for quick operations.
+- Long-term state should be maintained by your external source-of-truth workflow.
+
+### Then go here
+
+- [Operating Modes and Source of Truth](operating-modes.md)
+- [Advanced Configuration Reference](configuration-advanced.md)
+- [Scale Planning and Topology Design](scale-topology.md)
+- [Troubleshooting](troubleshooting.md)
+
+## Manual Files (<100 subscribers)
+
+### When to choose
+
+You intentionally maintain `network.json` + `ShapedDevices.csv` directly without CRM/NMS synchronization.
+
+Recommended only for networks under 100 subscribers.
+
+### Do this now
+
+1. Build and maintain shaping files directly.
+2. Place LibreQoS inline for pilot traffic.
+3. Validate shaping and scheduler status in WebUI.
+4. Maintain strict manual change discipline.
+5. Plan migration to supported integration or custom scripts if scale/change volume grows.
+
+### Then go here
+
+- [Advanced Configuration Reference](configuration-advanced.md)
+- [Operating Modes and Source of Truth](operating-modes.md)
+- [Scale Planning and Topology Design](scale-topology.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/_build/html/_sources/docs/v2.0/requirements.md.txt b/_build/html/_sources/docs/v2.0/requirements.md.txt
new file mode 100644
index 00000000..68bb1495
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/requirements.md.txt
@@ -0,0 +1,131 @@
+# System Requirements
+
+LibreQoS can be run either on a dedicated physical server (bare metal) or as a VM. Ubuntu Server 24.04 is the supported operating system.
+
+## Physical Server (Bare Metal)
+
+### CPU
+* 2 or more CPU cores are required
+* Choose a CPU with high [single-thread performance](https://www.cpubenchmark.net/singleThread.html#server-thread) within your budget. Queuing is CPU-intensive, and requires high single-thread performance.
+
+Single-thread CPU performance determines the maximum capacity of a single HTB (CPU core). This, in turn, affects the maximum capacity of any top-level node in the network hierarchy (e.g., top-level sites in your network). This also impacts the maximum speed plan you can offer customers within safe margins.
+
+| Single-Thread Score | Top-Level Node Max | Customer Plan Max |
+|:-------------------:|:------------------:|:-----------------:|
+| 1000 | 1 Gbps | 100 Mbps |
+| 1500 | 2 Gbps | 500 Mbps |
+| 2000 | 3 Gbps | 1 Gbps |
+| 3000 | 4 Gbps | 2 Gbps |
+| 4000 | 5 Gbps | 3 Gbps |
+
+Below is a table of approximate aggregate capacity, assuming a CPU with a [single thread](https://www.cpubenchmark.net/singleThread.html#server-thread) performance rating of 1000, 2000, 3000, or 4000:
+
+| CPU Cores | Single-Thread Score: 1000 | Single-Thread Score: 2000 | Single-Thread Score: 3000 | Single-Thread Score: 4000 |
+|:---------:|:-------------------------:|:-------------------------:|:-------------------------:|:-------------------------:|
+| 2 | 1 Gbps | 3 Gbps | 5 Gbps | 7 Gbps |
+| 4 | 3 Gbps | 5 Gbps | 9 Gbps | 13 Gbps |
+| 6 | 4 Gbps | 8 Gbps | 14 Gbps | 20 Gbps |
+| 8 | 5 Gbps | 10 Gbps | 18 Gbps | 27 Gbps |
+| 16 | 10 Gbps | 21 Gbps | 36 Gbps | 54 Gbps |
+| 32 | 21 Gbps | 42 Gbps | 72 Gbps | 108 Gbps |
+| 64 | 42 Gbps | 84 Gbps | 144 Gbps | 216 Gbps |
+| 128 | 84 Gbps | 168 Gbps | 288 Gbps | |
+
+### Hyper-threading
+
+Please [disable Hyper-Threading](prereq.md) (Simultaneous Multi-Threading) in the BIOS/UEFI settings, as it can interfere with XDP processing.
+
+### Memory
+* Recommended RAM:
+
+| RAM (using CAKE) | Max Subscribers |
+| ---------------- | --------------- |
+| 8 GB | 1,000 |
+| 16 GB | 2,500 |
+| 32 GB | 5,000 |
+| 64 GB | 10,000 |
+| 128 GB | 20,000 |
+
+### Disk Space
+
+50 GB of disk space or more is generally recommended, both for servers and VM deployments.
+
+### Device Recommendations
+#### Small Form Factor (1G to 10G)
+
+| Throughput | 10 Gbps |
+|:-----------------------:|:--------------------------------------------------------------------------------------:|
+| Per Node / Per CPU Core | 5 Gbps |
+| Manufacturer | Minisforum |
+| Model | [MS-01](https://store.minisforum.com/products/minisforum-ms-01?variant=46174128898293) |
+| CPU Option | i9-12900H |
+| RAM Option | 1x32GB |
+| NIC Option | Built-in |
+| Temp Range | 0°C ~ 40°C |
+| Temp Range | (32°F ~ 104°F) |
+| ECC | No |
+| Power | 19V DC |
+
+##### MS-01 Notes:
+
+As with any machine running LibreQoS, please be sure to [disable hyperthreading](prereq.md). Specific to the MS-01, please consider [replacing the thermal paste](https://www.youtube.com/watch?v=G70QtUAxomU) to lower CPU temps by about 20 degrees celcius (Note: this may void the warranty).
+
+#### Rackmount Servers (10G to 100G)
+
+| Throughput | 10 Gbps | 10 Gbps | 25 Gbps | 50 Gbps | 100 Gbps |
+|-------------------------|:------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------------:|:-----------------------------------------------------------------------------------:|
+| Per Node / Per CPU Core | 5 Gbps | 5 Gbps | 3 Gbps | 3 Gbps | 4 Gbps |
+| Manufacturer | Supermicro | Dell | Supermicro | Supermicro | Supermicro |
+| Model | [SYS-511R-M](https://store.supermicro.com/us_en/mainstream-1u-sys-511r-m.html) | [PowerEdge R260](https://www.dell.com/en-us/shop/dell-poweredge-servers/new-poweredge-r260-rack-server/spd/poweredge-r260/pe_r260_tm_vi_vp_sb?configurationid=2cd33e43-57a3-4f82-aa72-9d5f45c9e24c) | [AS-1115S-FWTRT](https://store.supermicro.com/us_en/1u-amd-epyc-8004-compact-server-as-1115s-fwtrt.html) | [AS-1015SV-WTNRT](https://store.supermicro.com/us_en/1u-amd-wio-as-1015sv-wtnrt.html) | [AS -2015CS-TNR](https://store.supermicro.com/us_en/clouddc-amd-as-2015cs-tnr.html) |
+| CPU Option | E-2488 | E-2456 | 8534P | 8534P | 9745 |
+| RAM Option | 1x32GB | 1x32GB | 4x16GB | 2x64GB | 4x64GB |
+| NIC Option | 10-Gigabit X710-BM2 (2 x SFP+) | Intel X710-T2L (2 x 10G RJ45) | Mellanox (2 x SFP28) | Mellanox 100-Gigabit (2 x QSFP56) | MCX653106A-HDAT |
+| Temp Range | 0°C ~ 40°C | 5–40°C | 0°C ~ 40°C | 0°C ~ 40°C | 0°C ~ 40°C |
+| Temp Range | (32°F ~ 104°F) | (41–104°F) | (32°F ~ 104°F) | (32°F ~ 104°F) | (32°F ~ 104°F) |
+| ECC | Yes | Yes | Yes | Yes | Yes |
+| Power | AC | AC | AC | AC | AC | |
+
+Another cost-effective solution is to procure a used server from a reputable vendor, such as [TheServerStore](https://www.theserverstore.com/).
+Such vendors often stock servers capable of 10 Gbps throughput, for around $500 USD.
+
+#### Server Setup Prerequisites
+
+[Server Setup Prerequisites](prereq.md)
+
+### Network Interface Requirements
+* One management network interface completely separate from the traffic shaping interfaces. Usually this would be the Ethernet interface built in to the motherboard.
+* A Dedicated Network Interface Card for Two Shaping Interfaces
+
+> **⚠️ Bonded Interfaces**: LibreQoS does not support the use of bonded interfaces. This is a limitation of XDP.
+
+Officially supported Network Interface Cards for the two shaping interfaces are listed below:
+
+| NIC Controller | Port Speed | Suggested Models | Known Issues |
+|------------------------|------------------|-----------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------|
+| Intel X520 | 10 Gbps | | Module compatibility* |
+| Intel X710 | 10 Gbps | [X710-BM2 10G]( https://www.fs.com/products/75600.html?now_cid=4253) | Module compatibility* |
+| Intel XXV710 | 10 / 25 Gbps | [XXV710 25G](https://www.fs.com/products/75604.html?attribute=67774&id=1709896) | Module compatibility* |
+| Intel XL710 | 10 / 40 Gbps | [XL710-BM2 40G](https://www.fs.com/products/75604.html?attribute=67774&id=1709896 ) | Module compatibility* |
+| Mellanox ConnectX-4 Lx | 10/25/40/50 Gbps | | No known issues. |
+| Mellanox ConnectX-6 | 10/25 Gbps | [MCX631102AN-ADAT](https://www.fs.com/products/212177.html?now_cid=4014) | No known issues. |
+| Mellanox ConnectX-6 | 100 Gbps | [MCX623106AN-CDAT 100G](https://www.fs.com/products/119646.html?now_cid=4014) | No known issues. |
+| Mellanox ConnectX-7 | 200 Gbps | [MCX755106AS-HEAT 200G](https://www.fs.com/products/242589.html?now_cid=4014) | No known issues. |
+
+(*) Intel often vendor-locks SFP+ module compatibility. Check module compatibility before buying. Mellanox does not have this problem.
+
+**We will ONLY provide support for systems using a NIC listed above**. Some other NICs *may* work, but will not be officially supported by LibreQoS. If you want to *test* the compatability of another card, please be aware of these fundamental NIC requirements:
+ * NIC must have multiple TX/RX transmit queues, greater than or equal to the number of CPU cores. [Here's how to check from the command line](https://serverfault.com/questions/772380/how-to-tell-if-nic-has-multiqueue-enabled).
+ * NIC must have [XDP driver support](https://github.com/xdp-project/xdp-project/blob/master/areas/drivers/README.org) for high-throughput (10 Gbps+).
+
+If you discover that a card not listed in the table above is compatible, please let us know by emailing support [at] libreqos.io.
+
+## Virtual Machine
+LibreQoS can be run as a VM, although this comes at a performance penalty of 30%. For VMs, NIC passthrough is required to achieve throughput above 10 Gbps (XDP vs generic XDP).
+LibreQoS requires 2 or more RX/TX queues, so when using a virtualization platform such as Proxmox, be sure to enable [Multiqueue](https://forum.proxmox.com/threads/where-is-multiqueue.146783/) for the shaping interfaces assigned to the VM. Multiqueue should be set equal to the number of vCPU cores assigned to the VM.
+
+| Throughput | vCPU* | RAM | Disk |
+|:-------:|:-----:|:-----:|:-----:|
+| 1 Gbps | 2 | 8 GB | 50 GB |
+| 10 Gbps | 8 | 32 GB | 50 GB |
+
+* Assumes vCPU performance equal to a single core of the Intel Xeon E-2456 with hyper-threading disabled.
diff --git a/_build/html/_sources/docs/v2.0/scale-topology.md.txt b/_build/html/_sources/docs/v2.0/scale-topology.md.txt
new file mode 100644
index 00000000..a46ae087
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/scale-topology.md.txt
@@ -0,0 +1,75 @@
+# Scale Planning and Topology Design
+
+This guide focuses on designing `network.json` and integration strategy choices for stable performance at scale.
+
+## Core Design Principles
+
+- Keep hierarchy only as deep as operationally necessary.
+- Avoid concentrating too much traffic under one top-level parent.
+- Prefer predictable naming and stable parent relationships to reduce queue churn.
+- Validate topology changes in a maintenance window before broad rollout.
+
+## Strategy Selection by Scale
+
+Use the simplest integration strategy that still meets operational needs:
+
+| Strategy | Typical Scale Fit | Tradeoff |
+|---|---|---|
+| `flat` | Maximum performance, minimal hierarchy | Lowest topology visibility/aggregation |
+| `ap_only` | Large AP-driven networks | Good performance, moderate visibility |
+| `ap_site` | Medium to large site/AP networks | Better aggregation with moderate overhead |
+| `full` | Networks requiring full path/backhaul representation | Highest control and highest CPU/memory cost |
+
+If `full` is required and you observe single-core saturation, use `promote_to_root` to distribute load.
+
+## Parent/Child Distribution Guidance
+
+Design goals:
+
+- Keep top-level parents balanced in traffic and circuit count.
+- Avoid very deep branch chains unless they add real shaping value.
+- Keep sibling naming unique and stable (important for virtual-node promotion and operational clarity).
+
+Warning signs:
+
+- One core persistently overloaded while others are mostly idle.
+- Frequent major queue rebuilds after small integration updates.
+- WebUI CPU Tree shows skewed distribution not explained by demand.
+
+## Virtual Nodes and Logical Grouping
+
+Virtual nodes are useful for logical organization and aggregation views.
+
+- Use virtual nodes to improve operability and reporting structure.
+- Do not use virtual nodes as a substitute for physical topology clarity.
+- Validate for name collisions after promotion behavior.
+
+## Queue/Classifier Guardrails
+
+At high scale, queue/class identifier pressure can become real.
+
+- Monitor for urgent issues such as `TC_U16_OVERFLOW`.
+- If encountered, reduce topology complexity and/or increase queue parallelism where appropriate.
+- Reassess strategy depth (`full` -> `ap_site`/`ap_only`) when overflow risk appears.
+
+See [Troubleshooting](troubleshooting.md#urgent-issue-codes-and-first-actions) for urgent-code response steps.
+
+## Rollout Checklist for Topology Changes
+
+1. Export current `network.json` and `ShapedDevices.csv` backups.
+2. Apply one topology change set at a time.
+3. Run/observe `lqos_scheduler` and `lqosd` logs after each change.
+4. Validate WebUI:
+ - CPU Tree / CPU Weights distribution
+ - Flow Map/ASN/Tree behavior
+ - scheduler status and urgent issues
+5. Keep a rollback copy of prior integration settings and topology files.
+
+## Related Pages
+
+- [Integrations](integrations.md)
+- [Performance Tuning](performance-tuning.md)
+- [StormGuard](stormguard.md)
+- [High Availability and Failure Domains](high-availability.md)
+- [Configuration](configuration.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/_build/html/_sources/docs/v2.0/stormguard.md.txt b/_build/html/_sources/docs/v2.0/stormguard.md.txt
new file mode 100644
index 00000000..be1739ef
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/stormguard.md.txt
@@ -0,0 +1,83 @@
+# StormGuard
+
+StormGuard is LibreQoS' adaptive queue-adjustment subsystem for congestion and quality events.
+
+> **Important Scope Warning**
+> StormGuard is intended for specific use cases, such as controlling congestion on variable-bandwidth WAN links (for example maritime networks), or a small number of access points with highly variable capacity.
+> It is not intended to manage dozens or hundreds of nodes at the same time.
+
+## What StormGuard Does
+
+- Monitors real-time signals (throughput, RTT/loss-related metrics, and saturation context).
+- Applies bounded adjustments to configured node limits to protect quality under stress.
+- Exposes status/debug data in the WebUI (Node Manager).
+
+## Configuration
+
+StormGuard is configured in `/etc/lqos.conf` under `[stormguard]`.
+
+Common keys:
+
+- `enabled`: turns StormGuard on/off.
+- `dry_run`: calculate decisions without applying live queue changes.
+- `targets`: list of top-level node names to manage.
+- `minimum_download_percentage`: minimum floor ratio for download limits.
+- `minimum_upload_percentage`: minimum floor ratio for upload limits.
+- `log_file`: optional CSV output path for decision/change telemetry.
+
+Example:
+
+```toml
+[stormguard]
+enabled = true
+dry_run = true
+log_file = "/var/log/stormguard.csv"
+targets = ["SITE_A", "SITE_B"]
+minimum_download_percentage = 0.5
+minimum_upload_percentage = 0.5
+```
+
+If you are testing, start with `dry_run = true` so you can observe decisions before allowing live limit changes.
+
+## UI and Debugging
+
+- WebUI provides StormGuard status and debug views.
+- The StormGuard debug page shows:
+ - current effective limits
+ - evaluation metrics
+ - rule/decision context
+
+Use this during rollout validation.
+
+## Safe Rollout Pattern
+
+1. Enable StormGuard with `dry_run = true`.
+2. Observe behavior for multiple peak periods.
+3. Validate there are no undesirable limit oscillations.
+4. Switch `dry_run = false`.
+5. Continue monitoring after each major topology/integration change.
+
+## Troubleshooting
+
+If StormGuard behavior seems incorrect:
+
+```bash
+sudo systemctl status lqosd lqos_scheduler
+journalctl -u lqosd --since "30 minutes ago"
+```
+
+Also verify:
+
+- target node names still match your current `network.json` hierarchy
+- integration updates have not renamed key nodes/APs
+- your minimum percentage floors are reasonable for expected traffic profiles
+- `log_file` path (if configured) is writable by the service user
+
+## Related Pages
+
+- [Configuration](configuration.md)
+- [Scale Planning and Topology Design](scale-topology.md)
+- [Performance Tuning](performance-tuning.md)
+- [High Availability and Failure Domains](high-availability.md)
+- [Components](components.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/_build/html/_sources/docs/v2.0/troubleshooting.md.txt b/_build/html/_sources/docs/v2.0/troubleshooting.md.txt
new file mode 100644
index 00000000..55f48e25
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/troubleshooting.md.txt
@@ -0,0 +1,251 @@
+# Troubleshooting
+
+## Start Here: Symptom Triage
+
+Use this table to jump to the first checks quickly.
+
+| Symptom | First check | WebUI location | Next section |
+|---|---|---|---|
+| Cannot access WebUI | `systemctl status lqosd` | N/A (UI unavailable) | No WebUI at x.x.x.x:9123 |
+| Traffic is not shaping | verify `to_internet` / `to_network`, service state | WebUI Dashboard | LibreQoS Is Running, But Traffic Not Shaping |
+| Scheduler appears unhealthy | check `lqosd` and `lqos_scheduler` logs | WebUI -> Scheduler Status | Scheduler status in WebUI looks unhealthy |
+| Topology/flow views blank | confirm recent traffic and `lqosd` health | WebUI -> Flow Map / Tree / ASN Explorer | Flow Map / Tree Overview / ASN Explorer appears blank |
+| Urgent issue code appears | open issue details and map code | WebUI -> Urgent Issues | Urgent issue codes and first actions |
+| Mapped circuit cap events | validate license state and mapped counts | Insight UI + WebUI -> Urgent Issues | Mapped circuit limit reached |
+
+## Common Issues
+
+### Where in WebUI
+
+- Service/health overview: `WebUI -> Dashboard`
+- Scheduler readiness: `WebUI -> Scheduler Status`
+- High-priority alerts: `WebUI -> Urgent Issues`
+- Topology/traffic visualization: `WebUI -> Network Tree Overview` and `Flow Map`
+- Shaped records review: `WebUI -> Shaped Devices Editor`
+
+### User password not working
+
+Delete the lqusers file:
+```
+sudo rm /opt/libreqos/src/lqusers.toml
+sudo systemctl restart lqosd lqos_scheduler
+```
+Then visit: BOX_IP:9123/index.html
+This will allow you to set up the user again from scratch using the WebUI.
+
+### No WebUI at x.x.x.x:9123
+
+The WebUI is controlled by the lqosd service. Usually, when the WebUI doesn't start, it is related to lqosd being in a failed state.
+Check to see if the lqosd service is running:
+```
+sudo systemctl status lqosd
+```
+
+If the status is 'failed', examine why using journalctl, which shows the full status of the service:
+```
+journalctl -u lqosd --since "10 minutes ago"
+```
+Press the End key on the keyboard to take you to the bottom of the log to see the latest updates to that log.
+
+Lqosd will provide specific reasons it failed, such as an interface not being up, an interface lacking multi-queue, or other cocnerns.
+
+### LibreQoS Is Running, But Traffic Not Shaping
+
+In /etc/lqos.conf, ensure that `to_internet` and `to_network` are set correctly. If not, simply swap the interfaces between those and restart lqosd and the scheduler.
+
+```
+sudo systemctl restart lqosd lqos_scheduler
+```
+
+Make sure your services are running properly
+
+```
+sudo systemctl status lqosd lqos_scheduler
+```
+
+The service lqos_scheduler is dependent on the lqosd service being in a healthy, running state.
+
+### On-a-stick shaping looks wrong or one direction is weak
+
+On-a-stick mode depends on queue splitting per direction. If TX queue discovery is wrong or `override_available_queues` is mis-set, directional mapping can be degraded.
+
+Check:
+```
+sudo systemctl status lqosd
+journalctl -u lqosd --since "10 minutes ago"
+```
+
+Then verify queue-related config in `/etc/lqos.conf` and restart:
+```
+sudo systemctl restart lqosd lqos_scheduler
+```
+
+### Service lqosd is not running or failed to start
+
+Check to see the state of the lqosd service:
+```
+sudo systemctl status lqosd
+```
+
+If the status is 'failed', examine why using journalctl, which shows the full status of the service:
+```
+journalctl -u lqosd --since "10 minutes ago"
+```
+Press the End key on the keyboard to take you to the bottom of the log to see the latest updates to that log.
+
+Lqosd will provide specific reasons it failed, such as an interface not being up, an interface lacking multi-queue, or other cocnerns.
+
+### Advanced lqosd debug
+
+At the command-line, run:
+```
+sudo RUST_LOG=info /opt/libreqos/src/bin/lqosd
+```
+which runs lqosd in debug mode, and will provide specifics regarding why it failed to start.
+
+### Service lqos_scheduler shows errors
+
+If `sudo systemctl status lqosd lqos_scheduler` reveals that the lqos_scheduler service has issues, you can export a comprehensive log of the errors to a file:
+```
+sudo journalctl -u lqos_scheduler --since "1 day ago" --no-pager > lqos_sched_log.txt
+```
+This exports a log file to lqos_sched_log.txt. You can review this file to see what caused the scheduler to error out.
+
+### Scheduler status in WebUI looks unhealthy
+
+Recent builds expose scheduler readiness/state in the WebUI (Node Manager).
+
+If scheduler status appears down/stale:
+1. Verify both services:
+```
+sudo systemctl status lqosd lqos_scheduler
+```
+2. Check recent scheduler logs:
+```
+journalctl -u lqos_scheduler --since "30 minutes ago"
+```
+3. Check lqosd bus/log state for scheduler-ready or scheduler-error messages:
+```
+journalctl -u lqosd --since "30 minutes ago"
+```
+4. If config/integration changes were recent, restart services cleanly:
+```
+sudo systemctl restart lqosd lqos_scheduler
+```
+
+If status repeatedly oscillates between ready/error, collect both logs and confirm integration credentials/timeouts in `/etc/lqos.conf`.
+
+### RTNETLINK answers: Invalid argument
+
+This tends to show up when the MQ qdisc cannot be added correctly to the NIC interface. This would suggest the NIC has insufficient RX/TX queues. Please make sure you are using the [recommended NICs](requirements.md).
+
+### Python ModuleNotFoundError in Ubuntu 24.04
+```
+pip uninstall binpacking --break-system-packages --yes
+sudo pip uninstall binpacking --break-system-packages --yes
+sudo pip install binpacking --break-system-packages
+pip uninstall apscheduler --break-system-packages --yes
+sudo pip uninstall apscheduler --break-system-packages --yes
+sudo pip install apscheduler --break-system-packages
+pip uninstall deepdiff --break-system-packages --yes
+sudo pip uninstall deepdiff --break-system-packages --yes
+sudo pip install deepdiff --break-system-packages
+```
+### All customer IPs are listed under Unknown IPs, rather than Shaped Devices in GUI
+```
+cd /opt/libreqos/src
+sudo systemctl stop lqos_scheduler
+sudo python3 LibreQoS.py
+```
+
+The console output from running LibreQoS.py directly provides more specific errors regarding issues with ShapedDevices.csv and network.json
+Once you have identified the error and fixed ShapedDevices.csv and/or Network.json, please then run
+
+```sudo systemctl start lqos_scheduler```
+
+### Flow Map / Tree Overview / ASN Explorer appears blank
+
+Some views require enough recent data to render meaningfully. If pages look empty:
+1. Confirm `lqosd` is healthy.
+2. Wait for traffic/data to accumulate.
+3. Reload the page after 1-2 minutes.
+4. Check logs for websocket or ticker warnings:
+```
+journalctl -u lqosd --since "10 minutes ago"
+```
+
+If still blank under normal traffic, collect recent logs and open an issue.
+
+### Virtual node promotion collision (network.json)
+
+If LibreQoS.py fails with an error like `Virtual node promotion collision: 'AP_A' already exists at this level.`, you have a `"virtual": true` node whose children get promoted into a parent level where a node with the same name already exists.
+
+Rename one of the colliding nodes (names must be unique among siblings after virtual-node promotion), or restructure the hierarchy so promoted children won’t collide.
+
+### Mapped circuit limit reached
+
+If logs mention messages like:
+- `Mapped circuit limit reached`
+- `Bakery mapped circuit cap enforced`
+
+LibreQoS is enforcing a mapped-circuit cap. In current builds, default behavior without active Insight licensing enforces a finite mapped-circuit limit.
+
+Recommended checks:
+1. Confirm Insight/license status in the UI.
+2. Review `lqosd` logs for requested/allowed/dropped counts.
+3. Reduce mapped circuit count (short term) or update licensing/limits (long term).
+
+### Urgent issue codes and first actions
+
+WebUI urgent issues include machine-readable codes. Use them to triage quickly.
+
+| Code | Meaning | First checks | Typical fix path |
+|---|---|---|---|
+| `MAPPED_CIRCUIT_LIMIT` | Bakery is enforcing a mapped-circuit limit. | Insight license status, `journalctl -u lqosd` for requested/allowed/dropped counts. | Reduce mapped circuits immediately or update license/limits. |
+| `TC_U16_OVERFLOW` | Queue/class minor IDs exceeded the Linux tc u16 range on a CPU queue. | `journalctl -u lqos_scheduler -u lqosd`, topology depth/queue distribution. | Increase queue count and/or simplify/rebalance hierarchy (for example with integration strategy or root promotion changes). |
+
+Operational pattern:
+1. Open urgent issue details in WebUI (code/message/context).
+2. Pull matching logs from `lqosd` and `lqos_scheduler`.
+3. Apply the immediate mitigation.
+4. Acknowledge/clear the issue in UI once stable.
+
+### Systemd segfault
+
+If you experience a segfault in systemd, this is a known issue in systemd [1](https://github.com/systemd/systemd/issues/36031) [2](https://github.com/systemd/systemd/issues/33643).
+To work around it, you can compile systemd from scratch:
+
+### Install build dependencies
+
+```
+sudo apt update
+sudo apt install build-essential git meson libcap-dev libmount-dev libseccomp-dev \
+libblkid-dev libacl1-dev libattr1-dev libcryptsetup-dev libaudit-dev \
+libpam0g-dev libselinux1-dev libzstd-dev libcurl4-openssl-dev
+```
+
+#### Clone systemd repository from github
+
+```
+git clone https://github.com/systemd/systemd.git
+cd systemd
+git checkout v257.5
+meson setup build
+meson compile -C build
+sudo meson install -C build
+```
+
+Then, reboot, and confirm the systemd version with `systemctl --version`
+
+```
+libreqos@libreqos:~$ systemctl --version
+systemd 257 (257.5)
+```
+
+## Related Pages
+
+- [Quickstart](quickstart.md)
+- [Configure LibreQoS](configuration.md)
+- [CRM/NMS Integrations](integrations.md)
+- [Scale Planning and Topology Design](scale-topology.md)
+- [Performance Tuning](performance-tuning.md)
diff --git a/_build/html/_sources/docs/v2.0/ubuntu-server.md.txt b/_build/html/_sources/docs/v2.0/ubuntu-server.md.txt
new file mode 100644
index 00000000..68dfa4ba
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/ubuntu-server.md.txt
@@ -0,0 +1,39 @@
+# Install Ubuntu Server
+
+You can download Ubuntu Server 24.04 LTS from here.
+At this time, only Ubuntu Server 24.04 is supported. Please be sure not to use other versions.
+
+1. Boot Ubuntu Server from USB.
+2. Follow the steps below to install Ubuntu Server.
+
+
+
+
+
+
+
+For the network interfaces, disable the shaping interfaces entirely. Then, set a static IP address on the management interface (100.99.0.4 is just an example).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ensure SSH server is enabled so you can more easily log into the server later.
+
+
+
+
+
+
+You can use scp or sftp to access files from your LibreQoS server for easier file editing. Here's how to access via scp or sftp using an [Ubuntu](https://www.addictivetips.com/ubuntu-linux-tips/sftp-server-ubuntu/) or [Windows](https://winscp.net/eng/index.php) machine.
diff --git a/_build/html/_sources/docs/v2.0/update.md.txt b/_build/html/_sources/docs/v2.0/update.md.txt
new file mode 100644
index 00000000..87e66497
--- /dev/null
+++ b/_build/html/_sources/docs/v2.0/update.md.txt
@@ -0,0 +1,48 @@
+# Upgrading
+
+```{warning}
+If you use the XDP bridge, traffic will briefly stop passing through the bridge when lqosd restarts (XDP bridge is only operating while lqosd runs).
+```
+
+## If you installed the .deb
+
+```
+cd ~
+sudo apt-get update
+sudo apt-get upgrade
+wget https://download.libreqos.com/{deb_url_v1_5}
+sudo apt install ./{deb_url_v1_5}
+sudo systemctl restart lqosd lqos_scheduler
+```
+
+Now reboot the LibreQoS box with:
+```
+sudo reboot
+```
+This will flush the old eBPF maps and load the latest LibreQoS version.
+
+## If you installed with Git
+
+1. Change to your LibreQoS directory (e.g. `cd /opt/libreqos`)
+2. Update from Git: `git pull`
+3. ```git switch develop```
+5. Recompile: `./build_rust.sh`
+6. `sudo rust/remove_pinned_maps.sh`
+
+Run the following commands to reload the LibreQoS services.
+
+```shell
+sudo systemctl restart lqosd lqos_scheduler
+```
+
+### Notes on pinned BPF maps
+
+`rust/remove_pinned_maps.sh` removes pinned maps used by the eBPF/XDP pipeline so newer map schemas can load cleanly after upgrades.
+
+Recent versions include additional map cleanup (including `ip_mapping_epoch`). If this cleanup is skipped after a schema-changing upgrade, you may see stale behavior or mapping inconsistencies.
+
+If you use Git installs, keep this order:
+1. build/update binaries
+2. stop/restart services as needed
+3. run `sudo rust/remove_pinned_maps.sh`
+4. restart `lqosd` and `lqos_scheduler`
diff --git a/_build/html/_sources/index.rst.txt b/_build/html/_sources/index.rst.txt
new file mode 100644
index 00000000..acc983d0
--- /dev/null
+++ b/_build/html/_sources/index.rst.txt
@@ -0,0 +1,49 @@
+.. LibreQoE documentation master file, created by
+ sphinx-quickstart on Fri May 19 10:37:27 2023.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Welcome to the LibreQoS documentation
+====================================
+
+.. toctree::
+ :maxdepth: 1
+ :caption: Getting Started
+
+ Quickstart (Start Here)
+ docs/v2.0/design
+ docs/v2.0/requirements
+ docs/v2.0/prereq
+ docs/v2.0/ubuntu-server
+ docs/v2.0/bridge
+
+.. toctree::
+ :maxdepth: 1
+ :caption: Managing LibreQoS (v1.5 to v2.0):
+
+ docs/v2.0/configuration
+ docs/v2.0/operating-modes
+ docs/v2.0/configuration-advanced
+ docs/v2.0/integrations
+ docs/v2.0/components
+ docs/v2.0/node-manager-ui
+ docs/v2.0/scale-topology
+ docs/v2.0/stormguard
+ docs/v2.0/high-availability
+ docs/v2.0/update
+ docs/v2.0/troubleshooting
+
+.. toctree::
+ :maxdepth: 1
+ :caption: Insight
+
+ docs/v2.0/insight
+ docs/v2.0/api
+
+.. toctree::
+ :maxdepth: 1
+ :caption: Misc:
+
+ docs/v2.0/cake
+ docs/v2.0/performance-tuning
+ docs/v2.0/extras
diff --git a/_build/html/_sources/src/AGENTS.md.txt b/_build/html/_sources/src/AGENTS.md.txt
new file mode 100644
index 00000000..98b0c7db
--- /dev/null
+++ b/_build/html/_sources/src/AGENTS.md.txt
@@ -0,0 +1,141 @@
+# AGENTS.md (LibreQoS local development guide)
+
+Purpose: provide consistent, machine-local instructions for AI coding agents working in `/opt/libreqos/src`.
+
+Status: draft v0.1, pending maintainer answers in the "Open Questions" section.
+
+## Scope and Priorities
+
+- Repository context: LibreQoS traffic-shaping stack for ISP/enterprise QoE, with Rust daemons and Python scheduler/integrations.
+- Primary goals for development work in this folder:
+ - Keep shaping behavior correct and safe for production networks.
+ - Preserve low-latency/low-loss QoE outcomes.
+ - Minimize operational risk to running systems.
+ - Keep changes small, focused, and testable.
+
+## Source-of-Truth References
+
+- Product/site: `https://libreqos.io/`
+- Docs in this workspace: `../docs/v2.0/`
+ - `quickstart.md`, `configuration.md`, `integrations.md`, `components.md`, `requirements.md`, `design.md`, `troubleshooting.md`, `update.md`, `performance-tuning.md`, `api.md`
+- Repo policies:
+ - `../README.md`
+ - `../CONTRIBUTING.md`
+
+When instructions conflict: prefer explicit maintainer direction > local AGENTS.md > repo docs.
+
+## Architecture Map (quick orientation)
+
+- Rust executables in `bin/`:
+ - `lqosd` (XDP/bridge + WebUI on :9123)
+ - `lqtop`, `lqusers`, `xdp_pping`, `xdp_iphash_to_cpu_cmdline`, `uisp_integration`, etc.
+- Rust source crates in `rust/` (notably `lqosd`, `lqos_config`, `lqos_queue_tracker`, `lqos_python`).
+- Python orchestration in this directory:
+ - `scheduler.py` (periodic refresh + integration orchestration)
+ - `LibreQoS.py` (queue/shaper setup logic)
+ - `integration*.py` (CRM/NMS imports: UISP/Splynx/Netzur/etc.)
+- System service examples:
+ - `bin/lqosd.service.example`
+ - `bin/lqos_scheduler.service.example`
+ - `bin/lqos_api.service.example`
+
+## Operational Safety Rules
+
+- Assume this host may be a live shaper node unless told otherwise.
+- Do not restart `lqosd`, `lqos_scheduler`, or `lqos_api` unless user explicitly asks.
+- Do not run destructive cleanup (`rm`, database/file wipes, map removal scripts) unless explicitly requested.
+- Treat these as runtime/generated artifacts; avoid manual edits unless task explicitly targets them:
+ - `ShapedDevices.csv`, `network.json`, `lastGoodConfig.*`, `statsBy*.json`, `queuingStructure.json`, `linux_tc*.txt`, `graph.*`
+- For `/etc/lqos.conf` guidance, provide exact diffs/commands but do not edit system files without confirmation.
+
+## Development Workflow Expectations
+
+- Keep each change set focused on one behavior or bug.
+- Prefer minimal invasive changes over refactors.
+- For Rust changes:
+ - Format: `cargo fmt` (crate or workspace as applicable).
+ - Build targeted crate(s) first; workspace build only when needed.
+ - Add/adjust unit tests when behavior changes are testable.
+- For Python changes:
+ - Run the narrowest script that validates the edited path.
+ - Keep integration failures non-fatal for scheduler loops unless behavior requires hard-fail.
+- For integration changes:
+ - Validate expected write targets (`ShapedDevices.csv`, optional `network.json`) and error logging paths.
+
+## Practical Command Reference
+
+- Build Rust + deploy binaries to `bin/`:
+ - `./build_rust.sh`
+- Build Debian package:
+ - `./build_dpkg.sh`
+- Update API binary:
+ - `./update_api.sh`
+- Manual scheduler debug:
+ - `python3 scheduler.py`
+- One-time shaping run/debug:
+ - `python3 LibreQoS.py`
+ - `python3 LibreQoS.py --debug`
+- Service health checks:
+ - `sudo systemctl status lqosd lqos_scheduler`
+ - `journalctl -u lqosd --since "10 minutes ago"`
+
+## Change Validation Checklist
+
+Before handing work back, agent should do what is feasible locally:
+
+- Confirm files compile/run for touched language area.
+- Confirm formatting/lint expectations for touched language area.
+- Run targeted tests for affected modules/crates if available.
+- Report exactly what was validated vs not validated.
+- Flag any need for privileged/system-level validation (services, NIC/XDP behavior, bridge traffic).
+
+## Communication Expectations for Agents
+
+- Be explicit about assumptions (especially if environment may be production).
+- Use absolute paths when referencing edited files.
+- If uncertain about operational impact, stop and ask before risky actions.
+- When suggesting troubleshooting, prefer commands documented in `../docs/v2.0/troubleshooting.md`.
+
+## Maintainer Decisions (Confirmed)
+
+These are explicit maintainer preferences and should be treated as policy on this machine/repo:
+
+- Insight terminology policy:
+ - LTS is deprecated for operator-facing docs.
+ - Do not reintroduce LTS as an active/current feature in docs.
+ - Legacy terms may appear in code/UI identifiers (`lts_*`), but docs should explain them as Insight-related legacy naming.
+
+- Sphinx release version handling:
+ - Keep `../conf.py` replacement values edited manually at major releases.
+ - Do not switch to environment-driven/version-auto-substitution workflow unless maintainers explicitly request it.
+
+- Documentation parity policy (EN/ES):
+ - Keep `../docs/v2.0` and `../docs-es/v2.0` aligned for operationally important content.
+ - When adding/removing major EN pages, update `../docs-es/index.rst` and provide ES counterparts.
+ - Prioritize parity for: install/update, configuration, integrations, troubleshooting, API, Insight, Node Manager, StormGuard, and scale/performance guidance.
+
+- Current docs structure expectations:
+ - EN docs include `node-manager-ui`, `stormguard`, and `scale-topology`.
+ - ES docs should include corresponding `*-es` pages and toctree entries.
+
+## Resolved Decisions (Additional)
+
+1. Service restarts:
+ - Agents must not restart services automatically.
+ - Restarting `lqosd`, `lqos_scheduler`, or `lqos_api` requires explicit maintainer request.
+
+2. Rust build strategy:
+ - Prefer targeted crate builds/tests first.
+ - Run full `./build_rust.sh` only when requested or when change scope requires it.
+
+3. Runtime data edits:
+ - Do not edit runtime data files (`ShapedDevices.csv`, `network.json`) during routine debugging unless explicitly requested.
+
+4. Privileged actions / service manipulation:
+ - Any `sudo` action that changes service/system state requires explicit maintainer direction.
+
+## Remaining Open Questions
+
+1. Which test commands are mandatory for PR-ready changes in this repo (Rust, Python, both)?
+2. Which branch workflow should agents assume on this machine (`develop` only, or current checked-out branch)?
+3. Any directories/files that must never be touched by agents beyond `.keys/` and generated artifacts?
diff --git a/_build/html/_sources/src/INSIGHT_SIGNUP_PLAN.md.txt b/_build/html/_sources/src/INSIGHT_SIGNUP_PLAN.md.txt
new file mode 100644
index 00000000..b9ba8c49
--- /dev/null
+++ b/_build/html/_sources/src/INSIGHT_SIGNUP_PLAN.md.txt
@@ -0,0 +1,259 @@
+We're building the Insight sign-up system.
+
+HTML files to work on:
+* `rust/lqosd/src/node_manager/static2/lts_trial.html`
+
+It's ok to use JavaScript. If you do, it will live in:
+* `rust/lqosd/src/node_manager/js_build/src/lts_trial.js`
+
+You can always verify compilation with the `esbuild.sh` script.
+
+The overall process is as follows:
+
+```mermaid
+flowchart TD
+START["User clicks 'Insight Trial' in LibreQoS UI"] --> TEASER["Display Teaser"]
+TEASER --> EXISTING{"Are you an existing customer?"}
+
+ EXISTING -->|Yes| LKEY["Enter License Key"]
+ LKEY --> VALIDATE_KEY["Validate Key"]
+ VALIDATE_KEY -->|Valid| SETUP["Write to lqos.conf and configure Insight"]
+ VALIDATE_KEY -->|Invalid| INVALID_KEY["Show error message"]
+ INVALID_KEY --> LKEY
+
+ LKEY -->|Forgot Key?| RECOVER["Recover License Key"]
+ RECOVER --> RECOVER_INPUT["Enter Email or Org Name"]
+ RECOVER_INPUT --> SEND_RECOVERY["Email License Key + Portal Access"]
+ SEND_RECOVERY --> LKEY
+
+ EXISTING -->|No| CAPTURE["Collect Customer Info"]
+ CAPTURE --> NEW_LKEY["Generate New License Key"]
+ NEW_LKEY --> SEND_CREDS["Email License Key + Portal Login"]
+ SEND_CREDS --> SETUP
+
+ SETUP --> CONGRATS["Show Setup Success and Thank You"]
+```
+
+This process cannot all be done in LibreQoS - all of the email sending, license generation, data
+storage (etc.) are handled by Insight (lts2). Insight is in a different repository.
+
+The `lts_trial.html` page needs to display the teaser data with the following requirements:
+* Use Bootstrap5 and FontAwesome (free) icons.
+* We're using jQuery for REST calls.
+* Use CSS that fits with other LibreQoS pages, including working with Day/Night modes.
+* Use the `lts_trial.js` file to handle the JavaScript logic. Remember the "cache busting" technique
+ to ensure the latest version is loaded. Check other HTML files for examples.
+
+The teaser itself should be modular, so we can add image/text for feature content to highlight. IDEALLY, you should
+define a schema for the teaser data to be loaded dynamically from a POST to the Insight server. The schema should be
+clearly documented. Each teaser should have a title, description and an image URL. The design should be responsive
+(with Bootstrap) and work well on mobile devices as well as desktops.
+
+Please *also* come up with a 3-item placeholder teaser that we can use for testing purposes. Use comments
+to make it clear where we will load the teaser data from the Insight server instead of using static test data.
+
+The page itself should:
+
+* Be a fragment so that the `template.rs` system can load it.
+* Display the teaser as a "jumbotron" or similar style panel.
+* Every teaser page should have two buttons:
+ * "I have a license key" - which will show the license key input form.
+ * "I want to try Insight for free" - which will show the customer info capture form.
+ * Both buttons should be styled with Bootstrap and use FontAwesome icons.
+
+For bonus points, use the existing dashboard API to find out how many active circuits the user has, and
+display that information - at a cost of $0.30 per circuit per month, this is a great deal!
+
+The "configure LibreQOS" step should be left as a placeholder, invoking a Rust function
+in `lqosd` that will configure `lqos.conf` and restart the service.
+This will be implemented later.
+
+## API Endpoints
+
+The following API endpoints are used in the `lts_trial.html` page:
+
+(Note that none of these are live yet, but will be implemented in the Insight server.)
+
+### License Key Validation
+
+`POST https://insight.libreqos.com/signup-api/validateLicense`
+Parameters: JSON
+```json
+{
+ "licenseKey": "your-license-key"
+}
+```
+
+Returns:
+```json
+{
+ "valid": true,
+ "message": "License key is valid."
+}
+```
+
+```json
+{
+ "valid": false,
+ "message": "Invalid license key."
+}
+```
+
+### License Key Recovery
+
+`POST https://insight.libreqos.com/signup-api/recoverLicense`
+
+Parameters: JSON
+```json
+{
+ "email": "email"
+}
+```
+
+Returns status code 200 whether it succeeded or not, and sends email if the email is valid and
+has a license key associated with it (to avoid fishing trips!)
+
+### Customer Info Capture
+
+`POST https://insight.libreqos.com/signup-api/signupCustomer`
+
+Parameters: JSON
+```json
+{
+ "nodeId": "(from lqos.conf)",
+ "name": "...",
+ "email": "...",
+ "business_name": "...",
+ "address1": "...",
+ "address2": "...",
+ "city": "...",
+ "state": "...",
+ "zip": "...",
+ "country": "...",
+ "phone": "...",
+ "website": "..."
+}
+```
+
+This will return status code 200 and a JSON body if the information was captured successfully,
+and a license key issued (sent by email to the user).
+
+```json
+{
+ "licenseKey": "new key"
+}
+```
+
+### Teasers
+
+`GET https://insight.libreqos.com/signup-api/teasers`
+
+This is unimplemented, and will mirror the schema we create for this process!
+
+### Analytics Tracking
+
+`GET https://insight.libreqos.com/signup-api/signupPing`
+
+A tracking pixel endpoint used for analytics funnel tracking. This is called at multiple points to track user flow:
+- When user clicks "I have a license key" button: `?t=&type=existing`
+- When user clicks "Start my free trial" button: `?t=&type=new`
+- When user submits the signup form: `?t=` (no type parameter)
+
+The request includes:
+- `t`: Cache-busting timestamp to ensure each ping is unique
+- `type` (optional): Indicates which path the user chose ("existing" or "new")
+
+No response body is expected - this is purely for server-side analytics tracking to help build conversion funnels.
+
+## Teaser Schema
+
+The teaser system is designed to showcase Insight features dynamically. The API endpoint returns a JSON response with the following schema:
+
+```json
+{
+ "teasers": [
+ {
+ "id": "string", // Unique identifier for the teaser
+ "title": "string", // Main headline for the feature
+ "description": "string", // Detailed description of the feature
+ "imageUrl": "string", // URL to feature image (hosted on Insight server)
+ // Recommended image size: 800x400px (2:1 ratio)
+ // Minimum: 600x300px, Format: JPG/PNG/WebP
+ // Images will be displayed with letterboxing to preserve aspect ratio
+ "features": [ // Optional: Bullet points highlighting key benefits
+ "string"
+ ],
+ "ctaText": "string", // Optional: Custom call-to-action text (default: "Try Insight Free")
+ "order": number // Optional: Display order (lower numbers appear first)
+ }
+ ],
+ "displayMode": "sequential" // Display mode: "sequential" or "random"
+}
+```
+
+### Example Response:
+```json
+{
+ "teasers": [
+ {
+ "id": "analytics",
+ "title": "Real-time Network Analytics",
+ "description": "Monitor your network performance with millisecond precision. Track bandwidth usage, latency, packet loss, and more in real-time.",
+ "imageUrl": "https://insight.libreqos.com/assets/analytics-dashboard.png",
+ "features": [
+ "Live bandwidth monitoring per circuit",
+ "Historical trend analysis",
+ "Automatic anomaly detection"
+ ],
+ "order": 1
+ },
+ {
+ "id": "reporting",
+ "title": "Advanced Reporting Suite",
+ "description": "Generate comprehensive reports with just a few clicks. Perfect for management meetings and customer insights.",
+ "imageUrl": "https://insight.libreqos.com/assets/reports-preview.png",
+ "features": [
+ "Customizable report templates",
+ "Scheduled email delivery",
+ "Export to PDF, CSV, or Excel"
+ ],
+ "ctaText": "Start Your Free Trial",
+ "order": 2
+ }
+ ],
+ "displayMode": "sequential"
+}
+```
+
+The client implementation will:
+- Cache teasers for 24 hours to reduce API calls
+- Fall back to static placeholder teasers if the API is unavailable
+- Support both sequential display (carousel) and random selection
+- Ensure all teasers have consistent sizing for a polished appearance
+
+## Validation
+
+Please validate all fields on the client side. At an absolute minimum, we HAVE to have their
+name, email, and location information (address, city, state, zip, country). We should also
+make sure we don't sign-up users from countries embargoed by the US government, such as Russia, Iran, North Korea, etc.
+etc.
+
+Country lists MUST be compatible with Paddle Billing (which Insight server users). The full
+list is here: https://developer.paddle.com/concepts/sell/supported-countries-locales
+
+We absolutely mustn't change the configuration of LibreQoS until we know everything worked.
+
+## Styling
+
+`help.html` is a decent Bootstrap5 example we use, as is the main dashboard page. Mostly, we
+want it to be clear, modern, accessible and responsive. Use existing pages for inspiration,
+but please feel free to innovate and make it look great!
+
+## Active Circuit Count
+
+The active circuit count should be located by counting circuits in the `ShapedDevices.csv` file. There's a ssection of
+of the `lqos_config` crate that can be used to read this file and count the active circuits. We may have
+to add a new API endpoint to the `lqosd` service to expose this information, but it should be straightforward.
+
+Make this a lower priority, towards the end of this process, as it is not critical to the sign-up flow.
+
diff --git a/_build/html/_sources/src/INSIGHT_SIGNUP_SERVER_PLAN.md.txt b/_build/html/_sources/src/INSIGHT_SIGNUP_SERVER_PLAN.md.txt
new file mode 100644
index 00000000..450646f4
--- /dev/null
+++ b/_build/html/_sources/src/INSIGHT_SIGNUP_SERVER_PLAN.md.txt
@@ -0,0 +1,393 @@
+# Insight Signup Server Implementation Plan
+
+This document describes the server-side implementation for the LibreQoS Insight signup API endpoints. The server will be implemented using FastAPI (Python web framework) and will integrate with existing databases.
+
+The overall process (including from the LibreQoS client side) is as follows:
+
+The overall process is as follows:
+
+```mermaid
+flowchart TD
+START["User clicks 'Insight Trial' in LibreQoS UI"] --> TEASER["Display Teaser"]
+TEASER --> EXISTING{"Are you an existing customer?"}
+
+ EXISTING -->|Yes| LKEY["Enter License Key"]
+ LKEY --> VALIDATE_KEY["Validate Key"]
+ VALIDATE_KEY -->|Valid| SETUP["Write to lqos.conf and configure Insight"]
+ VALIDATE_KEY -->|Invalid| INVALID_KEY["Show error message"]
+ INVALID_KEY --> LKEY
+
+ LKEY -->|Forgot Key?| RECOVER["Recover License Key"]
+ RECOVER --> RECOVER_INPUT["Enter Email or Org Name"]
+ RECOVER_INPUT --> SEND_RECOVERY["Email License Key + Portal Access"]
+ SEND_RECOVERY --> LKEY
+
+ EXISTING -->|No| CAPTURE["Collect Customer Info"]
+ CAPTURE --> NEW_LKEY["Generate New License Key"]
+ NEW_LKEY --> SEND_CREDS["Email License Key + Portal Login"]
+ SEND_CREDS --> SETUP
+
+ SETUP --> CONGRATS["Show Setup Success and Thank You"]
+```
+
+## Overview
+
+The Insight signup server provides API endpoints for:
+- License key validation and recovery
+- New customer registration
+- Teaser content delivery
+- Analytics tracking
+
+## Overall Design
+
+* The project must be in Python.
+* Ideally using FastAPI for the server implementation.
+* There must be a clear `venv` setup with requirements etc.
+* There must be a Dockerfile setup, see the `python/paddle_webhooks` project for an example.
+* There must be clear integration into the Docker Compose setup (in `remote_setup/services/insight`).
+
+## Technology Stack
+
+- **Framework**: FastAPI (Python)
+- **Database**: TBD (PostgreSQL/MySQL - to be integrated with existing Insight infrastructure)
+- **Email Service**: Use the existing `mailer_svc` NATS service for sending emails
+- **Authentication**: API endpoints are public (no auth required for signup flow). I don't really like this, but I don't see a way to lock this down?
+
+## Teaser Storage
+
+The teasers should be stored as a JSON file that can be loaded dynamically. The schema is further down in this
+document. The docker compose setup should explose this as a directory, so that the server can read the file -
+and we can edit it as needed without redeploying the server. There's no need to complicate this with a database.
+
+### Static Images
+
+"Teaser" entries can include a static image URL. This should point to `/signup-api/image?id=teaser-id` and log
+that the image was loaded for analytics purposes. The server should serve these images from a static directory.
+The images should be exposed as a directory via the Docker Compose setup, so they can be easily updated without redeploying the server.
+
+## Email Templates
+
+There are several items that send email. The `mailer_svc` NATS service will handle sending the emails. It has
+a handlebars templating system and allows for complex HTML templates as well as plain text. We'll need to
+expand our plan to include all of the appropriate email templates. A bonus would be to store these in a docker-compose
+exposed directory, so that we can edit them without redeploying the server.
+
+## API Endpoints
+
+### 1. Validate License Key
+
+**Endpoint**: `POST /signup-api/validateLicense`
+
+**Purpose**: Validates an existing license key
+
+**Request Body**:
+```json
+{
+ "licenseKey": "XXXX-XXXX-XXXX-XXXX"
+}
+```
+
+**Response (Success - 200)**:
+```json
+{
+ "valid": true,
+ "message": "License key is valid."
+}
+```
+
+**Response (Invalid - 200)**:
+```json
+{
+ "valid": false,
+ "message": "Invalid license key."
+}
+```
+
+**Implementation Notes**:
+- License key format: 4 groups of 4 alphanumeric characters, separated by hyphens (always a valid v4 UUID)
+- Case-insensitive validation
+- Check against database of issued license keys
+- Log validation attempts for security monitoring
+
+---
+
+### 2. Recover License Key
+
+**Endpoint**: `POST /signup-api/recoverLicense`
+
+**Purpose**: Sends license key recovery email to registered email addresses
+
+**Request Body**:
+```json
+{
+ "email": "user@example.com"
+}
+```
+
+**Response (Always 200)**:
+```json
+{
+ "status": "ok"
+}
+```
+
+**Implementation Notes**:
+- ALWAYS return 200 OK to prevent email fishing
+- If email exists in database:
+ - Send email with all license keys associated with that email
+ - Include portal login link
+- If email doesn't exist: do nothing
+- Rate limit: Max 3 requests per email per hour
+- Log all recovery attempts
+
+**Email Template**:
+```
+Subject: Your LibreQoS Insight License Key(s)
+
+Hello,
+
+You requested your LibreQoS Insight license key(s). Here are all licenses associated with your email:
+
+License Key: XXXX-XXXX-XXXX-XXXX
+Organization: [Org Name]
+Status: [Active/Expired]
+
+You can access the Insight portal at: https://insight.libreqos.com/portal
+
+If you didn't request this email, please ignore it.
+
+Best regards,
+LibreQoS Team
+```
+
+---
+
+### 3. Register New Customer
+
+**Endpoint**: `POST /signup-api/signupCustomer`
+
+**Purpose**: Creates new customer account and issues trial license
+
+**Request Body**:
+```json
+{
+ "nodeId": "node-uuid-from-lqos-conf",
+ "name": "John Doe",
+ "email": "john@example.com",
+ "business_name": "Example ISP",
+ "address1": "123 Main St",
+ "address2": "Suite 100",
+ "city": "Anytown",
+ "state": "CA",
+ "zip": "12345",
+ "country": "us",
+ "phone": "+1-555-123-4567",
+ "website": "https://example.com"
+}
+```
+
+**Required Fields**: nodeId, name, email, business_name, address1, city, state, zip, country, phone
+
+**Response (Success - 200)**:
+```json
+{
+ "licenseKey": "XXXX-XXXX-XXXX-XXXX"
+}
+```
+
+**Response (Error - 400)**:
+```json
+{
+ "error": "Invalid country code"
+}
+```
+
+**Implementation Notes**:
+- Validate all required fields
+- Country must be in allowed list (exclude embargoed countries)
+- Email must be unique (one license per email)
+- Generate unique license key
+- Create customer record in database
+- Send welcome email with license key and portal credentials
+- Create trial subscription (30 days)
+- Log signup for analytics
+
+**Welcome Email Template**:
+```
+Subject: Welcome to LibreQoS Insight - Your Trial Has Started!
+
+Hello [Name],
+
+Welcome to LibreQoS Insight! Your 30-day trial has been activated.
+
+Your License Key: XXXX-XXXX-XXXX-XXXX
+
+Portal Access:
+URL: https://insight.libreqos.com/portal
+Email: [email]
+Password: [temporary password]
+
+Your trial includes:
+- Real-time network analytics
+- Advanced reporting suite
+- Proactive alerts
+- Full API access
+
+Getting Started:
+1. Your LibreQoS system should now be connected to Insight
+2. Log into the portal to view your network analytics
+3. Check out our documentation at https://docs.libreqos.com/insight
+
+Questions? Reply to this email or visit our support portal.
+
+Best regards,
+LibreQoS Team
+```
+
+---
+
+### 4. Get Teaser Content
+
+**Endpoint**: `GET /signup-api/teasers`
+
+**Purpose**: Returns dynamic teaser content for the signup page
+
+**Response (Success - 200)**:
+```json
+{
+ "teasers": [
+ {
+ "id": "analytics",
+ "title": "Real-time Network Analytics",
+ "description": "Monitor your network performance with millisecond precision. Track bandwidth usage, latency, packet loss, and more in real-time.",
+ "imageUrl": "https://insight.libreqos.com/assets/analytics-dashboard.png",
+ "features": [
+ "Live bandwidth monitoring per circuit",
+ "Historical trend analysis",
+ "Automatic anomaly detection"
+ ],
+ "ctaText": "Try Insight Free",
+ "order": 1
+ },
+ {
+ "id": "reporting",
+ "title": "Advanced Reporting Suite",
+ "description": "Generate comprehensive reports with just a few clicks. Perfect for management meetings and customer insights.",
+ "imageUrl": "https://insight.libreqos.com/assets/reports-preview.png",
+ "features": [
+ "Customizable report templates",
+ "Scheduled email delivery",
+ "Export to PDF, CSV, or Excel"
+ ],
+ "ctaText": "Start Your Free Trial",
+ "order": 2
+ },
+ {
+ "id": "alerts",
+ "title": "Proactive Alerts",
+ "description": "Get notified before issues impact your customers with intelligent monitoring and predictive analytics.",
+ "imageUrl": "https://insight.libreqos.com/assets/alert-system.png",
+ "features": [
+ "Customizable alert thresholds",
+ "Multi-channel notifications",
+ "Intelligent issue prediction"
+ ],
+ "order": 3
+ }
+ ],
+ "displayMode": "sequential"
+}
+```
+
+**Implementation Notes**:
+- Cache response for 24 hours
+- Images should be 800x400px (2:1 ratio)
+- Can be static or dynamically generated based on A/B testing
+- Consider adding more teasers for different feature sets
+
+---
+
+### 5. Analytics Tracking Pixel
+
+**Endpoint**: `GET /signup-api/signupPing`
+
+**Purpose**: Tracks user interactions for conversion funnel analytics
+
+**Query Parameters**:
+- `t`: Timestamp (for cache busting)
+- `type` (optional): "existing" or "new" (indicates which path user chose)
+
+**Examples**:
+- User clicks "I have a license key": `/signup-api/signupPing?t=1703001234567&type=existing`
+- User clicks "Start my free trial": `/signup-api/signupPing?t=1703001234568&type=new`
+- User submits signup form: `/signup-api/signupPing?t=1703001234569`
+
+**Response**: 1x1 transparent PNG image
+
+**Implementation Notes**:
+- Log timestamp, IP address, user agent, type
+- Track conversion funnel:
+ - Page views (when teaser loads)
+ - Path selection (existing vs new)
+ - Form submissions
+- Use for marketing analytics and optimization
+- Consider adding session tracking via cookies
+
+---
+
+## Database Schema
+
+Existing database tables are found in the `db_setup` project, and we'd like to use them. We can make
+modifications to the schema if we need to, but we should try to avoid that if possible.
+
+## Security Considerations
+
+1. **Rate Limiting**:
+ - License validation: 10 attempts per IP per minute
+ - Recovery emails: 3 per email per hour
+ - Signups: 5 per IP per hour
+
+2. **Input Validation**:
+ - Sanitize all inputs
+ - Validate email formats
+ - Check country codes against allowed list
+ - License key format validation
+
+3. **Logging**:
+ - Log all API requests
+ - Monitor for suspicious patterns
+ - Alert on repeated failed validations
+
+4. **CORS**:
+ - Unfortunately, people might be running shapers anywhere - so we need very relaxed CORS settings.
+
+---
+
+## Testing Considerations
+
+1. **Unit Tests**:
+ - Test each endpoint with valid/invalid data
+ - Test rate limiting
+ - Test email sending (mock SMTP)
+
+2. **Integration Tests**:
+ - Test full signup flow
+ - Test database operations
+ - Test email delivery
+
+3. **Load Tests**:
+ - Simulate high traffic on tracking pixel
+ - Test concurrent signups
+ - Verify rate limiting under load
+
+---
+
+## Deployment Notes
+
+1. Use environment variables for:
+ - Database credentials
+ - NATS information
+ - See the `remote_setup/services/insight` directory for how things are currently setup.
+
+2. Integrate with the nginx reverse proxy - both sites (one is via Cloudflare, the other direct).
+ - You can find the setup in `remote_setup/storage/nginx_conf` directory.
\ No newline at end of file
diff --git a/_build/html/_sources/src/INTEGRATION_HOWTO.md.txt b/_build/html/_sources/src/INTEGRATION_HOWTO.md.txt
new file mode 100644
index 00000000..61466105
--- /dev/null
+++ b/_build/html/_sources/src/INTEGRATION_HOWTO.md.txt
@@ -0,0 +1,182 @@
+# LibreQoS Integrations
+
+If you need to create an integration for your network, we've tried to give you the tools you need. We currently ship integrations for UISP and Splynx. We'd love to include more.
+
+### Overall Concept
+
+LibreQoS enforces customer bandwidth limits, and applies CAKE-based optimizations at several levels:
+
+* Per-user Cake flows are created. These require the maximum bandwidth permitted per customer.
+ * Customers can have more than one device that share a pool of bandwidth. Customers are grouped into "circuits"
+* *Optional* Access points can have a speed limit/queue, applied to all customers associated with the access point.
+* *Optional* Sites can contain access points, and apply a speed limit/queue to all access points (and associated circuits).
+* *Optional* Sites can be nested beneath other sites and access point, providing for a queue hierarchy that represents physical limitations of backhaul connections.
+
+Additionally, you might grow to have more than one shaper - and need to express your network topology from the perspective of different parts of your network. (For example, if *Site A* and *Site B* both have Internet connections - you want to generate an efficient topology for both sites. It's helpful if you can derive this from the same overall topology)
+
+LibreQoS's network modeling accomplishes this by modeling your network as a *graph*: a series of interconnected nodes, each featuring a "parent". Any "node" (entry) in the graph can be turned into a "root" node, allowing you to generate the `network.json` and `ShapedDevices.csv` files required to manage your customers from the perspective of that root node.
+
+### Flat Shaping
+
+The simplest form of integration produces a "flat" network. This is the highest performance model in terms of raw throughput, but lacks the ability to provide shaping at the access point or site level: every customer site is parented directly off the root.
+
+> For an integration, it's recommended that you fetch the customer/device data from your management system rather than type them all in Python.
+
+A flat integration is relatively simple. Start by importing the common API:
+
+```python
+from integrationCommon import isIpv4Permitted, fixSubnet, NetworkGraph, NetworkNode, NodeType
+```
+
+Then create an empty network graph (it will grow to represent your network):
+
+```python
+net = NetworkGraph()
+```
+
+Once you have your `NetworkGraph` object, you start adding customers and devices. Customers may have any number of devices. You can add a single customer with one device as follows:
+
+```python
+# Add the customer
+customer = NetworkNode(
+ id="Unique Customer ID",
+ displayName="The Doe Family",
+ type=NodeType.client,
+ download=100, # Download is in Mbit/second
+ upload=20, # Upload is in Mbit/second
+ address="1 My Road, My City, My State")
+net.addRawNode(customer) # Insert the customer ID
+
+# Give them a device
+device = NetworkNode(
+ id="Unique Device ID",
+ displayName="Doe Family CPE",
+ parentId="Unique Customer ID", # must match the customer's ID
+ type=NodeType.device,
+ ipv4=["100.64.1.5/32"], # As many as you need, express networks as the network ID - e.g. 192.168.100.0/24
+ ipv6=["feed:beef::12/64"], # Same again. May be [] for none.
+ mac="00:00:5e:00:53:af"
+)
+net.addRawNode(device)
+```
+
+If the customer has multiple devices, you can add as many as you want - with `ParentId` continuing to match the parent customer's `id`.
+
+Once you have entered all of your customers, you can finish the integration:
+
+```python
+net.prepareTree() # This is required, and builds parent-child relationships.
+net.createNetworkJson() # Create `network.json`
+net.createShapedDevices() # Create the `ShapedDevices.csv` file.
+```
+
+### Detailed Hierarchies
+
+Creating a full hierarchy (with as many levels as you want) uses a similar strategy to flat networks---we recommend that you start by reading the "flat shaping" section above.
+
+Start by importing the common API:
+
+```python
+from integrationCommon import isIpv4Permitted, fixSubnet, NetworkGraph, NetworkNode, NodeType
+```
+
+Then create an empty network graph (it will grow to represent your network):
+
+```python
+net = NetworkGraph()
+```
+
+Now you can start to insert sites and access points. Sites and access points are inserted like customer or device nodes: they have a unique ID, and a `ParentId`. Customers can then use a `ParentId` of the site or access point beneath which they should be located.
+
+For example, let's create `Site_1` and `Site_2` - at the top of the tree:
+
+```python
+net.addRawNode(NetworkNode(id="Site_1", displayName="Site_1", parentId="", type=NodeType.site, download=1000, upload=1000))
+net.addRawNode(NetworkNode(id="Site_2", displayName="Site_2", parentId="", type=NodeType.site, download=500, upload=500))
+```
+
+Let's attach some access points and point-of-presence sites:
+
+```python
+net.addRawNode(NetworkNode(id="AP_A", displayName="AP_A", parentId="Site_1", type=NodeType.ap, download=500, upload=500))
+net.addRawNode(NetworkNode(id="Site_3", displayName="Site_3", parentId="Site_1", type=NodeType.site, download=500, upload=500))
+net.addRawNode(NetworkNode(id="Site_5", displayName="Site_5", parentId="Site_3", type=NodeType.site, download=200, upload=200))
+net.addRawNode(NetworkNode(id="AP_9", displayName="AP_9", parentId="Site_5", type=NodeType.ap, download=120, upload=120))
+net.addRawNode(NetworkNode(id="Site_6", displayName="Site_6", parentId="Site_5", type=NodeType.site, download=60, upload=60))
+net.addRawNode(NetworkNode(id="AP_11", displayName="AP_11", parentId="Site_6", type=NodeType.ap, download=30, upload=30))
+net.addRawNode(NetworkNode(id="Site_4", displayName="Site_4", parentId="Site_2", type=NodeType.site, download=200, upload=200))
+net.addRawNode(NetworkNode(id="AP_7", displayName="AP_7", parentId="Site_4", type=NodeType.ap, download=100, upload=100))
+net.addRawNode(NetworkNode(id="AP_1", displayName="AP_1", parentId="Site_2", type=NodeType.ap, download=150, upload=150))
+```
+
+When you attach a customer, you can specify a tree entry (e.g. `Site_5`) as a parent:
+
+```python
+# Add the customer
+customer = NetworkNode(
+ id="Unique Customer ID",
+ displayName="The Doe Family",
+ parentId="Site_5",
+ type=NodeType.client,
+ download=100, # Download is in Mbit/second
+ upload=20, # Upload is in Mbit/second
+ address="1 My Road, My City, My State")
+net.addRawNode(customer) # Insert the customer ID
+
+# Give them a device
+device = NetworkNode(
+ id="Unique Device ID",
+ displayName="Doe Family CPE",
+ parentId="Unique Customer ID", # must match the customer's ID
+ type=NodeType.device,
+ ipv4=["100.64.1.5/32"], # As many as you need, express networks as the network ID - e.g. 192.168.100.0/24
+ ipv6=["feed:beef::12/64"], # Same again. May be [] for none.
+ mac="00:00:5e:00:53:af"
+)
+net.addRawNode(device)
+```
+
+Once you have entered all of your network topology and customers, you can finish the integration:
+
+```python
+net.prepareTree() # This is required, and builds parent-child relationships.
+net.createNetworkJson() # Create `network.json`
+net.createShapedDevices() # Create the `ShapedDevices.csv` file.
+```
+
+You can also add a call to `net.plotNetworkGraph(False)` (use `True` to also include every customer; this can make for a HUGE file) to create a PDF file (currently named `network.pdf.pdf`) displaying your topology. The example shown here looks like this:
+
+
+
+### Per‑Circuit SQM Overrides (Download/Upload)
+
+LibreQoS supports optional per‑circuit SQM overrides via the last column (`sqm`) of `ShapedDevices.csv`.
+
+- Accepted values:
+ - Single token: `cake`, `fq_codel`, or `none` (applies to both directions)
+ - Directional: `down_sqm/up_sqm` where each side is one of `cake`, `fq_codel`, `none`, or empty
+- Directional semantics:
+ - Left token is download, right token is upload (e.g., `cake/fq_codel`)
+ - Either side may be empty to leave that direction at default (e.g., `cake/` or `/fq_codel`)
+ - `none` disables the SQM qdisc for that direction
+- Normalization: Values are trimmed and lower‑cased; case is ignored on load
+- Defaults and fast‑queues: If a side is unspecified (empty) or the entire field is empty, the global default SQM applies for that side. The “fast queues to fq_codel” threshold is evaluated per direction when no explicit override is set.
+
+Examples:
+
+```
+# Both directions cake
+...,cake
+
+# Download cake, upload fq_codel
+...,cake/fq_codel
+
+# Download explicit (fq_codel), upload default
+...,fq_codel/
+
+# Disable upload SQM only
+...,/none
+```
+
+## Longest Prefix Match Tip
+You could theoretically throttle all unknown IPs until they are associated with a client. For example, you could limit every unknown to 1.5x0.5 with single entry in ShapedDevices.csv, until you associate them with an account. IPs need to be non-exact matches. So you can't have two 192.168.1.1 entries, but you can have a 192.168.1.0/24 subnet and a 192.168.1.2/32 - they aren't duplicates, and the LPM search is smart enough to pick the most exact match.
diff --git a/_build/html/_sources/src/README.md.txt b/_build/html/_sources/src/README.md.txt
new file mode 100644
index 00000000..10834468
--- /dev/null
+++ b/_build/html/_sources/src/README.md.txt
@@ -0,0 +1,9 @@
+# v1.4 (Alpha)
+
+
+
+See [wiki here](https://github.com/LibreQoE/LibreQoS/wiki/v1.4)
+
+## Binpacking
+
+LibreQoS assigns circuits and sites to CPU queues using a simple, deterministic greedy binpacking approach. We continue to use Insight (lts) to provide weights when available, but assignments themselves are computed on each run without keeping long‑term state.
diff --git a/_build/html/_sources/src/TESTING-1.4.md.txt b/_build/html/_sources/src/TESTING-1.4.md.txt
new file mode 100644
index 00000000..2bafc991
--- /dev/null
+++ b/_build/html/_sources/src/TESTING-1.4.md.txt
@@ -0,0 +1,188 @@
+# How to Test V1.4
+
+Version 1.4 is still undergoing active development, but if you'd like to benefit from it right now (or help us test/develop it!), here's a guide.
+
+ Please see the [v1.4 Wiki](https://github.com/LibreQoE/LibreQoS/wiki/v1.4) which replaces this document.
+
+## Updating from v1.3
+### Remove cron tasks from v1.3
+Run ```sudo crontab -e``` and remove any entries pertaining to LibreQoS from v1.3.
+
+## Clone the repo
+
+The recommended install location is `/opt/libreqos`.
+Go to the install location, and clone the repo:
+
+```
+cd /opt/
+git clone https://github.com/LibreQoE/LibreQoS.git libreqos
+sudo chown YOUR_USER /opt/libreqos -R
+```
+By specifying `libreqos` at the end, git will ensure the folder name is lowercase.
+
+> Now that this is in `main`, you no longer need to switch git branch. If you were previously on the `v1.4-pre-alpha-rust-integration` branch, please switch to main with `git checkout main; git pull`.
+
+## Install Dependencies from apt and pip
+
+You need to have a few packages from `apt` installed:
+
+```
+apt-get install -y python3-pip clang gcc gcc-multilib llvm libelf-dev git nano graphviz curl screen llvm pkg-config linux-tools-common linux-tools-`uname -r` libbpf-dev
+```
+
+Then you need to install some Python dependencies:
+
+```
+python3 -m pip install ipaddress schedule influxdb-client requests flask flask_restful flask_httpauth waitress psutil binpacking graphviz
+```
+
+## Install the Rust development system
+
+Go to [RustUp](https://rustup.rs) and follow the instructions. Basically, run the following:
+
+```
+curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
+```
+
+When Rust finishes installing, it will tell you to execute a command to place the Rust build tools into your path. You need to either execute this command or logout and back in again.
+
+Once that's done, change directory to `/wherever_you_put_libreqos/src/`, and run:
+
+```
+./build_rust.sh
+```
+
+This will take a while the first time, but it puts everything in the right place.
+Remember to run this command everytime after `git pull`.
+
+Now, run:
+```
+cd /src/rust
+cargo build --all
+```
+Again, please run this command everytime after `git pull`.
+
+## Setup the LibreQoS Daemon
+
+Copy the daemon configuration file to `/etc`:
+
+```
+sudo cp lqos.example /etc/lqos.conf
+```
+
+Now edit the file to match your setup:
+
+```toml
+lqos_directory = '/opt/libreqos/src'
+queue_check_period_ms = 1000
+
+[tuning]
+stop_irq_balance = true
+netdev_budget_usecs = 8000
+netdev_budget_packets = 300
+rx_usecs = 8
+tx_usecs = 8
+disable_rxvlan = true
+disable_txvlan = true
+disable_offload = [ "gso", "tso", "lro", "sg", "gro" ]
+
+interface_mapping = [
+ { name = "enp1s0f1", redirect_to = "enp1s0f2", scan_vlans = false },
+ { name = "enp1s0f2", redirect_to = "enp1s0f1", scan_vlans = false }
+]
+vlan_mapping = []
+```
+
+Change `enp1s0f1` and `enp1s0f2` to match your network interfaces. It doesn't matter which one is which.
+
+## Configure LibreQoS
+
+Follow the regular instructions to set your interfaces in `ispConfig.py` and your `network.json` and `ShapedDevices.csv` files.
+
+## Option A: Run as systemd services
+
+```
+sudo cp /opt/libreqos/src/bin/lqos_node_manager.service.example /etc/systemd/system/lqos_node_manager.service
+sudo cp /opt/libreqos/src/bin/lqosd.service.example /etc/systemd/system/lqosd.service
+sudo cp /opt/libreqos/src/bin/lqos_scheduler.service.example /etc/systemd/system/lqos_scheduler.service
+sudo systemctl daemon-reload
+sudo systemctl enable lqosd lqos_node_manager lqos_scheduler
+```
+lqos_scheduler handles statistics and performs continuous refreshes of LibreQoS' shapers, including pulling from any enabled CRM Integrations (UISP, Splynx).
+* On start: Run a full setup of queues
+* Every 10 seconds: Graph bandwidth and latency stats
+* Every 30 minutes: Update queues, pulling new configuration from CRM integration if enabled
+
+## Option B: Run in debug mode
+
+You can setup `lqosd` and `lqos_node_manager` as daemons to keep running (there are example `systemd` files in the `src/bin` folder). Since v1.4 is under such heavy development, I recommend using `screen` to run detached instances - and make finding issues easier.
+
+1. Stop services: systemctl stop lqosd lqos_node_manager
+2. `screen`
+3. `cd /wherever_you_put_libreqos/src/bin`
+4. `sudo ./lqosd`
+5. Create a new `screen` window with `Ctrl-A, C`.
+6. Run the webserver with `./lqos_node_manager`
+7. If you didn't see errors, detach with `Ctrl-A, D`
+
+You can now point a web browser at `http://a.b.c.d:9123` (replace `a.b.c.d` with the management IP address of your shaping server) and enjoy a real-time view of your network.
+
+In the web browser, click `Reload LibreQoS` to setup your shaping rules.
+
+## Updating 1.4 Once You Have It
+
+* Note: On January 22nd 2023 /etc/lqos was changed to /etc/lqos.conf to remedy Issue #205. If upgrading, be sure to move /etc/lqos to /etc/lqos.conf
+* Note: If you use the XDP bridge, traffic will stop passing through the bridge during the update (XDP bridge is only operating while lqosd runs).
+
+### If using systemd services
+
+1.
+```
+sudo systemctl stop lqos_scheduler lqos_node_manager lqosd
+```
+2. Change to your `LibreQoS` directory (e.g. `cd /opt/LibreQoS`)
+3. Update from Git: `git pull`
+4. Recompile: `./build_rust.sh`
+5.
+```
+cd /src/rust
+cargo build --all
+```
+6.
+```
+sudo systemctl start lqosd lqos_node_manager lqos_scheduler
+```
+
+### If running debug mode
+
+1. Resume screen with `screen -r`
+2. Go to console 0 (`Ctrl-A, 0`) and stop `lqosd` with `ctrl+c`.
+3. Go to console 1 (`Ctl-A, 1`) and stop `lqos_node_manager` with `ctrl+c`.
+4. Detach from `screen` with `Ctrl-A, D`.
+5. Change to your `LibreQoS` directory (e.g. `cd /opt/libreqos`)
+6. Update from Git: `git pull`
+7. Recompile: `./build_rust.sh`
+8. Run: `rust/remove_pinned_maps.sh`
+9. Resume screen with `screen -r`.
+10. Go to console 0 (`Ctrl-A, 0`) and run `sudo ./lqosd` to restart the bridge/manager.
+11. Go to console 1 (`Ctrl-A, 1`) and run `./lqos_node_manager` to restart the web server.
+12. If you didn't see errors, detach with `Ctrl-A, D`
+
+## Bugfix for slowly Ubuntu starting (~2 minutes penalty) in situation when one of the networking interface is down during startup
+
+#List all services which requires network
+```
+systemctl show -p WantedBy network-online.target
+```
+
+#For my Ubuntu 22.04 instance this command helped
+```
+systemctl disable cloud-config iscsid cloud-final
+```
+
+## Performance tips
+
+#Set proper governor for CPU (baremetal/hypervisior host)
+```
+cpupower frequency-set --governor performance
+```
diff --git a/_build/html/_sources/src/dist/libreqos_1.5-RC3.202601081232-1_amd64/opt/libreqos/src/README.md.txt b/_build/html/_sources/src/dist/libreqos_1.5-RC3.202601081232-1_amd64/opt/libreqos/src/README.md.txt
new file mode 100644
index 00000000..10834468
--- /dev/null
+++ b/_build/html/_sources/src/dist/libreqos_1.5-RC3.202601081232-1_amd64/opt/libreqos/src/README.md.txt
@@ -0,0 +1,9 @@
+# v1.4 (Alpha)
+
+
+
+See [wiki here](https://github.com/LibreQoE/LibreQoS/wiki/v1.4)
+
+## Binpacking
+
+LibreQoS assigns circuits and sites to CPU queues using a simple, deterministic greedy binpacking approach. We continue to use Insight (lts) to provide weights when available, but assignments themselves are computed on each run without keeping long‑term state.
diff --git a/_build/html/_sources/src/error_handling/README.md.txt b/_build/html/_sources/src/error_handling/README.md.txt
new file mode 100644
index 00000000..7e242907
--- /dev/null
+++ b/_build/html/_sources/src/error_handling/README.md.txt
@@ -0,0 +1,19 @@
+# Comprehensively handling errors from the OS is a difficult job
+# In test, they rarely happen. In production, doing sane things
+# IN ALL CASES, is sane.
+
+# Deciding what the sane things are, for each error return, is hard.
+
+# The example pinned.c file is a good example - What goes wrong if
+# ANY of these operations fail? What are the symptoms? Merely
+# removing the file does not mean that the daemon holding it open
+# notices
+
+See:
+
+https://github.com/LibreQoE/LibreQoS/issues/209
+https://github.com/LibreQoE/LibreQoS/issues/208
+https://github.com/LibreQoE/LibreQoS/issues/118
+
+And several closed bugs, where EEXIST was not an error. Etc.
+
diff --git a/_build/html/_sources/src/rust/README.md.txt b/_build/html/_sources/src/rust/README.md.txt
new file mode 100644
index 00000000..d9430236
--- /dev/null
+++ b/_build/html/_sources/src/rust/README.md.txt
@@ -0,0 +1,32 @@
+# Rust Management System for LibreQoS
+
+> Very much a work in progress. Details will be filled out as it stabilizes.
+
+## Sub Projects
+
+This project contains a number of projects arranged in a workspace. The projects are:
+
+* `lqos_sys` - a library that builds, installs, removes and manages the LibreQoS XDP and TC programs.
+* `lqos_bus` - definitions and helper functions for passing data across the local management bus.
+* `lqos_config` - a crate that handles pulling configuration from the Python manager.
+* `lqosd` - the management daemon that should eventually be run as a `systemd` service.
+ * When started, the daemon sets up XDP/TC eBPF programs for the interfaces specified in the LibreQoS configuration.
+ * When exiting, all eBPF programs are unloaded.
+ * Listens for bus commands and applies them.
+* `lqtop` - A CLI tool that outputs the top X downloaders and mostly verifies that the bus and daemons work.
+* `xdp_iphash_to_cpu_cmdline` - An almost-compatible command that acts like the tool of the same name from the previous verion.
+* `xdp_pping` - Port of the previous release's `xdp_pping` tool, for compatibility. Will eventually not be needed.
+
+## Required Ubuntu packages
+
+* `clang`
+* `linux-tools-common` (for `bpftool`)
+* `libbpf-dev`
+* `gcc-multilib`
+* `llvm`
+* `pkg-config`
+* `linux-tools-5.15.0-56-generic` (the common version doesn't work?)
+
+## Helper Scripts
+
+* `remove_pinned_maps.sh` deletes all of the BPF shared maps. Useful during development.
diff --git a/_build/html/_sources/src/rust/lqos_bakery/README.md.txt b/_build/html/_sources/src/rust/lqos_bakery/README.md.txt
new file mode 100644
index 00000000..f65fe7ed
--- /dev/null
+++ b/_build/html/_sources/src/rust/lqos_bakery/README.md.txt
@@ -0,0 +1,32 @@
+# LibreQoS Bakery
+
+> The bakery is where the CAKE is made!
+
+The bakery implements TC commands required to build the HTB and CAKE structures.
+It also provides longer-term queue tracking, allowing for the "lazy" creation of queues.
+
+It communicates with the rest of the system via the bus.
+
+## Features
+
+* `LibreQoS.py` no longer directly makes calls to `tc` commands, instead it uses the `Bakery` class (in `lqos_python`) to do so.
+* Queue structure is batched, and passed in a single pass to the `lqos_bakery` thread.
+* By default, it works exactly as before (with support for fractional bandwidths).
+
+In `lqos.conf`, you can add two items to the `[queues]` section:
+
+```toml
+lazy_queues = "No" # Default: "No"
+lazy_expire_seconds = 0 # 0 Disables lazy queue expiration
+```
+
+You have the following options:
+
+* `lazy_queues = "Htb"`: All HTB bandwidth-limiting queues will be created when `LibreQoS.py` runs (including by the scheduler). This ensures that you don't have a sudden burst of unshaped traffic. CAKE queues are created lazily, within 1 second of traffic being detected.
+* `lazy_queues = "Full"`: All queues are created lazily, within 1 second of traffic being detected.
+
+If you set `lazy_expire_seconds` to a value greater than 0, the bakery will also remove queues that have not been
+used for that many seconds. This is useful for long-term idle queues that you don't want to keep around forever. The
+default expiration time is 600 seconds (10 minutes). If you set it to 0, queues will never be removed.
+
+> It is NOT recommended to set `lazy_expire_seconds` to a very short time-period (under 60 seconds), as this can cause flapping.
diff --git a/_build/html/_sources/src/rust/lqos_bus/CONTRIBUTING.md.txt b/_build/html/_sources/src/rust/lqos_bus/CONTRIBUTING.md.txt
new file mode 100644
index 00000000..66aedd77
--- /dev/null
+++ b/_build/html/_sources/src/rust/lqos_bus/CONTRIBUTING.md.txt
@@ -0,0 +1,55 @@
+# Contributing to `lqos_bus`
+
+Thanks for your interest in improving the LibreQoS bus crate.
+
+## License and Exceptions
+
+- Contributions are accepted under: `AGPL-3.0-or-later WITH LicenseRef-LibreQoS-Exception`.
+- The exception is defined in `LICENSE` as AGPLv3 §7 “Additional permissions” for:
+ - LibreQoS Linking Exception (GPL-2.0-only combination with LibreQoS), and
+ - LibreQoE Internal-Use Exception (internal proprietary combination and deployment by LibreQoE LLC).
+- By submitting a contribution (e.g., PR/patch), you affirm you have the right to do so and you agree to license your contribution under these terms, including the exceptions.
+
+## SPDX Headers (required)
+
+All new and modified source files must include SPDX headers at the top of the file. For Rust files:
+
+```rust
+// SPDX-FileCopyrightText: 2025 LibreQoE support@libreqos.io
+// SPDX-License-Identifier: AGPL-3.0-or-later WITH LicenseRef-LibreQoS-Exception
+```
+
+Use appropriate comment styles for other languages. Keep years and names current.
+
+## Development Guidelines
+
+- Style: run `cargo fmt` for formatting and `cargo clippy -p lqos_bus --all-features` for linting.
+- Build: ensure `cargo build -p lqos_bus --all-features` succeeds without warnings where practical.
+- Dependencies: prefer well-maintained crates with compatible licenses. Avoid adding strong copyleft conflicts beyond what the AGPL already imposes.
+- API stability: the bus is intentionally unstable; document protocol changes in PRs.
+
+## Commit and PR Tips
+
+- Keep changes focused; include rationale and any performance/compatibility notes.
+- If your change affects external integrations, note migration steps.
+- Include tests where feasible or a short plan for manual verification.
+
+## Developer Certificate of Origin (DCO)
+
+We use a lightweight DCO process. Please add a Signed-off-by line to your commits:
+
+```
+Signed-off-by: Your Name
+```
+
+This certifies that you have the right to submit the work under the project license and exceptions.
+
+## Security and Sensitive Info
+
+- Do not include secrets or customer data in issues or PRs.
+- Report security concerns privately to support@libreqos.io.
+
+## Questions
+
+Open a discussion/issue or email support@libreqos.io. Thank you for contributing!
+
diff --git a/_build/html/_sources/src/rust/lqos_bus/README.md.txt b/_build/html/_sources/src/rust/lqos_bus/README.md.txt
new file mode 100644
index 00000000..c063b286
--- /dev/null
+++ b/_build/html/_sources/src/rust/lqos_bus/README.md.txt
@@ -0,0 +1,26 @@
+# LQOS Bus
+
+The bus acts as an intermediary through which `lqosd` and various clients communicate. The Python integration system, `lqtop` and other CLI tools use it to interact with `lqosd`.
+
+The bus is intentionally not stable between releases. So if you integrate with it, you will need to update your integration *every time* you update `lqosd`. This:
+
+* Allows for rapid iteration on the back-end.
+* Avoids the need for version negotiation (CBOR tolerates unknown enum variants).
+* Uses CBOR serialization with length-prefixed chunked framing for large payloads.
+
+> If you'd like a stable API, please consider the HTTP API provided with Insight.
+
+## Licensing
+
+The LibreQoS Bus system is also separately licensed. We use the [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.en.html) license for the bus system, with the explicit exception that LibreQoS itself and all products produced by LibreQoE LLC are exempt and licensed separately.
+
+We made this decision to ensure that the bus remains free and open source, and clients that add functionality to LibreQoS will also remain free and open source---even if you host it as a service. However, we do not want to force LibreQoS itself to be AGPL-3.0, as we want to allow for commercial use of LibreQoS itself.
+
+Any contributions to the bus system must include permission to use this license, *including* "carve-outs" for LibreQoS itself and all products produced by LibreQoE LLC.
+
+## Contributing
+
+Please read `CONTRIBUTING.md` before submitting patches.
+
+- SPDX for contributions: `AGPL-3.0-or-later WITH LicenseRef-LibreQoS-Exception`.
+- The exception terms are defined in `LICENSE` under AGPLv3 §7 “Additional permissions”.
diff --git a/_build/html/_sources/src/rust/lqos_config/README.md.txt b/_build/html/_sources/src/rust/lqos_config/README.md.txt
new file mode 100644
index 00000000..dda8461f
--- /dev/null
+++ b/_build/html/_sources/src/rust/lqos_config/README.md.txt
@@ -0,0 +1,23 @@
+# LQosConfig
+
+`lqos_config` is designed to manage configuration of LibreQoS. Starting in 1.5, all configuration is
+centralized into `/etc/lqos.conf`.
+
+The `lqos_python` module contains functions that mirror each of these, using their original Python
+names for integration purposes.
+
+You can find the full definitions of each configuration entry in `src/etc/v15`.
+
+## Adding Configuration Items
+
+There are two ways to add a configuration:
+
+1. Declare a Major Version Break. This is a whole new setup that will require a new configuration and migration. We should avoid doing this very often.
+ 1. You need to create a new folder, e.g. `src/etc/v16`.
+ 2. You need to port as much of the old config as you are creating.
+ 3. You need to update `src/etc/migration.rs` to include code to read a "v15" file and create a "v16" configuration.
+ 4. *This is a lot of work and should be a planned effort!*
+2. Declare an optional new version item. This is how you handle "oh, I needed to snoo the foo" - and add an *optional* configuration item - so nothing will snarl up because it isn't there.
+ 1. Find the section you want to include it in in `src/etc/v15`. If there isn't one, create it using one of the others as a template and be sure to include the defaults. Add it into `top_config` as the type `Option`.
+ 2. Update `example.toml` to include what *should* go there.
+ 3. Go into `lqos_python` and in `lib.rs` add a Python "getter" for the field. Remember to use `if let` to read the `Option` and return a default if it isn't present.
diff --git a/_build/html/_sources/src/rust/lqos_queue_tracker/src/queue_types/CAKE.md.txt b/_build/html/_sources/src/rust/lqos_queue_tracker/src/queue_types/CAKE.md.txt
new file mode 100644
index 00000000..69fb7d55
--- /dev/null
+++ b/_build/html/_sources/src/rust/lqos_queue_tracker/src/queue_types/CAKE.md.txt
@@ -0,0 +1,28 @@
+ways_collisions, if you are seeing a lot of these, it's indicative of a ping flood of some kind.
+ thresh 6Mbit
+ target 5.0ms
+ interval 100.0ms
+these are the bandwidth and codel settiings. On a vpn interface, or in a place where the typical rtt is to sydney and back, you can set rtt lower in cake, otherwise, don't touch.
+ pk_delay 440us
+ av_delay 13us
+ sp_delay 2us
+All these are ewmas (I forget the interval). pk_delay would be a good statistic to graph, tho I suspect that the highest peak delays would be on the lowest end plans, so peak delay by plan would pull out folk that were above average here.
+av_delay is pretty useless, like all averages, IMHO. Still I could be wrong.
+sp_delay = sparse delay and is an indicator of overload. Customers with the largest sparse delay would be interesting. Ideally this number never cracks 2ms.
+backlog - a persistent backlog is OK, but a sign that someone is using a torrent-like app, doing a big backup, or underprovisioned in some way. Seeing a persistent backlog in an AP on the other hand says the AP is overloaded.
+pkts
+bytes
+do what they say and are a summary statistic since invokation of cake.
+way_inds
+way_mis
+way_cols are indicators of how well the FQ is working, but not ver good ones.
+drops
+marks
+ack_drop
+in general I care about pkts, ack_drops, drops and marks, most, these are best plotted together on an invlog scale. When last I looked robert was combining drops and marks to treat as drops (which they are), but I am caring about the rise of ECN in general. As for the top 10 approach, the largest number of drops or marks relative to packets, would be useful.
+ sp_flows 1
+ bk_flows 1
+ un_flows 0
+bulk_flows indicate large transfers. They have nothing to do with diffserv marks, they are just bulk.
+max_len - if this is greater than your MTU, GRO and GSO are loose on your network.
+Quantum varies as a function of bandwidth, it may be 300 is more optimal than an MTU even at higher bandwidths than we first tested cake at.
\ No newline at end of file
diff --git a/_build/html/_sources/src/rust/lqos_setup/README-es.md.txt b/_build/html/_sources/src/rust/lqos_setup/README-es.md.txt
new file mode 100644
index 00000000..0d1cb247
--- /dev/null
+++ b/_build/html/_sources/src/rust/lqos_setup/README-es.md.txt
@@ -0,0 +1,29 @@
+# Configuración de LibreQoS
+
+Esta es la herramienta de configuración de LibreQoS, diseñada para ejecutarse automáticamente como parte del proceso de instalación con `dpkg`. Su objetivo principal es ayudar a los usuarios a establecer rápidamente una configuración mínima funcional de LibreQoS, asegurando que el sistema esté listo para operar con la menor intervención manual posible.
+
+## Propósito
+
+La herramienta de configuración de LibreQoS guía a los usuarios a través de los pasos esenciales necesarios para poner LibreQoS en funcionamiento. Simplifica el proceso inicial de configuramiento al proporcionar una interfaz guiada y automatiza la creación de los archivos de configuración necesarios.
+
+## Qué Configura la Herramienta
+
+La herramienta ayuda a configurar los siguientes componentes:
+
+- **Modo Puente (Bridge)**: Seleccione entre los modos Linux, XDP o Puente Único para adaptarse a su escenario de implementación.
+- **Interfaces de Red**: Eliga y configure las interfaces de red que LibreQoS gestionará.
+- **Parámetros de Ancho de Banda**: Establezca límites y parámetros de ancho de banda para su red.
+- **Rangos de IP**: Defina los rangos de direcciones IP que LibreQoS debe monitorear y regular.
+- **Usuarios Web**: Cree y gestione cuentas de usuario para acceder a la interfaz web de LibreQoS.
+- **Archivos de Configuración**: Genera y actualiza automáticamente los principales archivos de configuración, incluyendo:
+ - `lqos.conf`
+ - `network.json`
+ - `ShapedDevices.csv`
+
+## Interfaz de Usuario
+
+La herramienta de configuración proporciona una Interfaz de Usuario en Texto construida con la librería [Cursive](https://github.com/gyscos/cursive). Esta interfaz permite a los usuarios navegar de manera interactiva por las opciones de configuración en la terminal, haciendo que el proceso de instalación sea sencillo y amigable.
+
+## Integración con LibreQoS
+
+Al ejecutar esta herramienta durante la instalación, LibreQoS garantiza que todas las configuraciones críticas estén definidas y que el sistema esté listo para su uso inmediato. La herramienta de configuración es una parte integral del sistema LibreQoS, agilizando la implementación y reduciendo el riesgo de errores de configuración.
diff --git a/_build/html/_sources/src/rust/lqos_setup/README.md.txt b/_build/html/_sources/src/rust/lqos_setup/README.md.txt
new file mode 100644
index 00000000..35cfcd8b
--- /dev/null
+++ b/_build/html/_sources/src/rust/lqos_setup/README.md.txt
@@ -0,0 +1,29 @@
+# LibreQoS Setup
+
+This is the setup tool for LibreQoS, designed to be run automatically as part of the `dpkg` installation process. Its primary goal is to help users quickly establish a minimal working configuration for LibreQoS, ensuring that the system is ready for operation with minimal manual intervention.
+
+## Purpose
+
+The LibreQoS setup tool guides users through the essential configuration steps required to get LibreQoS up and running. It simplifies the initial setup process by providing a guided interface and automating the creation of necessary configuration files.
+
+## What the Setup Tool Configures
+
+The tool assists in configuring the following components:
+
+- **Bridge Mode**: Select between Linux, XDP, or Single bridge modes to match your deployment scenario.
+- **Network Interfaces**: Choose and configure the network interfaces that LibreQoS will manage.
+- **Bandwidth Settings**: Set bandwidth limits and parameters for your network environment.
+- **IP Ranges**: Define the IP address ranges that LibreQoS should monitor and shape.
+- **Web Users**: Create and manage web user accounts for accessing the LibreQoS web interface.
+- **Configuration Files**: Automatically generates and updates key configuration files, including:
+ - `lqos.conf`
+ - `network.json`
+ - `ShapedDevices.csv`
+
+## User Interface
+
+The setup tool provides a TUI (Text User Interface) built with the [Cursive](https://github.com/gyscos/cursive) library. This interface allows users to navigate configuration options interactively in the terminal, making the setup process straightforward and user-friendly.
+
+## Integration with LibreQoS
+
+By running this tool during installation, LibreQoS ensures that all critical settings are defined and that the system is ready for immediate use. The setup tool is an integral part of the overall LibreQoS system, streamlining deployment and reducing the potential for misconfiguration.
diff --git a/_build/html/_sources/src/rust/lqos_stormguard/README.md.txt b/_build/html/_sources/src/rust/lqos_stormguard/README.md.txt
new file mode 100644
index 00000000..853c7388
--- /dev/null
+++ b/_build/html/_sources/src/rust/lqos_stormguard/README.md.txt
@@ -0,0 +1,56 @@
+# LibreQoS StormGuard
+
+**WARNING**: This is extremely experimental. Don't try this on anyone you like.
+
+LibreQoS StormGuard. Automatic top-level HTB rate adjustment, based on capacity monitoring.
+
+Heavily inspired by LynxTheCat's Cake AutoRate project. https://github.com/lynxthecat/cake-autorate
+
+## Usage
+
+Add the following to your `lqos.conf`:
+
+```toml
+[stormguard]
+enabled = true
+dry_run = true
+log_file = "/tmp/stormguard.csv" # Optional
+targets = [ "CALVIN 1" ]
+minimum_download_percentage = 0.5 # For 50% of download as minimum
+minimum_upload_percentage = 0.5 # For 50% of upload as minimum
+```
+
+| **Entry Name** | **Description** |
+|----------------|-----------------------------------------------------------------------------------------------------------|
+| `enabled` | Enable or disable Tornado. Default: `false` |
+| `dry_run` | If true, Tornado will not change the rate. It will only log what it *would* have done. Default: `false` |
+| `log_file` | If set, a CSV will be appended with time (unix secs), download rate, upload rate entries. Default: absent |
+
+You can list as many sites as you want in the `targets` array. I strongly recommend `dry_run` for now, which just
+emits what it *would* have done to the console!
+
+## How it works
+
+StormGuard maintains a ring-buffer of recent throughput, TCP retransmits and TCP round-trip times for each target site.
+These are updated once per second, when `lqosd` "ticks". A second buffer maintains a moving average of a larger time period.
+
+Each circuit also maintains a "current queue bandwidth", which is adjusted dynamically. If `dry_run` is not set,
+this is applied directly to the HTB queue associated with the monitoring.
+
+> *Warning*: Do not apply this to HTB circuits that have a directly attached CAKE instance.
+
+Periodically:
+
+* Saturation is calculated as current throughput / max throughput.
+* Live saturation is calculated as current throughput / current queue bandwidth.
+* Retransmits are set to either High, RisingFast, Rising, Stable, Falling, FallingFast.
+* RTT is set to either Rising, Stable or Falling.
+
+These are fed through a decision matrix to determine if the queue bandwidth should be increased or decreased.
+
+Changes have a "cool-down" following their application, during which monitoring will continue but no changes will be made.
+This is to prevent oscillation between two states.
+
+## Running StormGuard
+
+StormGuard is integrated into `lqosd`. If it is enabled, it will run automatically when `lqosd` is started.
\ No newline at end of file
diff --git a/_build/html/_sources/src/rust/lqos_sys/README.md.txt b/_build/html/_sources/src/rust/lqos_sys/README.md.txt
new file mode 100644
index 00000000..88342d5b
--- /dev/null
+++ b/_build/html/_sources/src/rust/lqos_sys/README.md.txt
@@ -0,0 +1,7 @@
+## lqos_sys
+
+This crate wraps the XDP component in externally callable Rust. This is
+used by other systems to manage the XDP/TC eBPF system.
+
+The `src/bpf` directory contains the C for the eBPF program, as well as
+some wrapper helpers to bring it into Rust-space.
diff --git a/_build/html/_sources/src/rust/lqos_utils/src/temporal_heatmap_design.md.txt b/_build/html/_sources/src/rust/lqos_utils/src/temporal_heatmap_design.md.txt
new file mode 100644
index 00000000..691ec568
--- /dev/null
+++ b/_build/html/_sources/src/rust/lqos_utils/src/temporal_heatmap_design.md.txt
@@ -0,0 +1,81 @@
+# TemporalHeatmap Design
+
+## Goals
+
+- Keep a fixed-size, pre-allocated rolling window for 15 minutes of data.
+- Store 60 raw samples (1 per second) for the current minute and 14 summary blocks for prior minutes.
+- Track download, upload, RTT (optional), and TCP retransmit percentage (optional).
+- Provide median values per 1-minute block for 15 blocks total.
+- Avoid allocations in steady state; no persistence; optional use of Box for heap storage.
+
+## Data Layout
+
+Constants:
+
+- RAW_SAMPLES = 60
+- SUMMARY_BLOCKS = 14
+- TOTAL_BLOCKS = 15
+
+Fields (per instance):
+
+- raw_download: [Option; RAW_SAMPLES]
+- raw_upload: [Option; RAW_SAMPLES]
+- raw_rtt: [Option; RAW_SAMPLES]
+- raw_retransmit: [Option; RAW_SAMPLES]
+- summary_download: [Option; SUMMARY_BLOCKS]
+- summary_upload: [Option; SUMMARY_BLOCKS]
+- summary_rtt: [Option; SUMMARY_BLOCKS]
+- summary_retransmit: [Option; SUMMARY_BLOCKS]
+- raw_index: usize (0..RAW_SAMPLES)
+- raw_filled: usize (0..RAW_SAMPLES)
+
+All arrays are initialized to None so partial minutes do not skew medians.
+
+## Methods
+
+Public:
+
+- new() / default(): pre-allocate arrays and initialize indices.
+- add_sample(download: f32, upload: f32,
+ rtt_down: Option, rtt_up: Option,
+ retransmit_down: Option, retransmit_up: Option)
+ - Combine RTT and retransmit values:
+ - If both present, use average.
+ - If only one present, use that.
+ - If neither present, store None.
+ - Store download/upload and combined RTT/retransmit at raw_index.
+ - Increment raw_index and raw_filled.
+ - When raw_index reaches RAW_SAMPLES:
+ - Compute median for each metric from raw_* (ignoring None values).
+ - Shift summary_* left by one and append new median at the end.
+ - Reset raw_* to None and raw_index/raw_filled to 0.
+- blocks() -> HeatmapBlocks
+ - Returns 15 blocks for each metric.
+ - Blocks 0..SUMMARY_BLOCKS-1 mirror summary_* in oldest->newest order.
+ - Block TOTAL_BLOCKS-1 is computed from raw_* via median (ignoring None).
+ - If there are no samples for a block, return None for that slot.
+
+Helpers:
+
+- median(values: &mut [f32], len: usize) -> Option
+ - Build a scratch buffer with present samples.
+ - Sort and select middle element (or average of two middles).
+
+## Output Type
+
+- HeatmapBlocks { download: [Option; TOTAL_BLOCKS], upload: [Option; TOTAL_BLOCKS],
+ rtt: [Option; TOTAL_BLOCKS], retransmit: [Option; TOTAL_BLOCKS] }
+
+## Size and Memory Notes
+
+- Fixed-size: 4 * (RAW_SAMPLES + SUMMARY_BLOCKS) = 296 Option values.
+- Option is typically 8 bytes, so arrays are ~2368 bytes plus indices.
+- Document the exact size formula in the Rust doc comment for TemporalHeatmap.
+- Use arrays (or boxed arrays) to ensure no allocation growth after construction.
+
+## Median Rules
+
+- Missing samples (None) are ignored.
+- If no samples exist for a block, return None for that block.
+- For even counts, use the average of the two middle values.
+
diff --git a/_build/html/_sources/src/rust/lqosd/README.md.txt b/_build/html/_sources/src/rust/lqosd/README.md.txt
new file mode 100644
index 00000000..92f6eb50
--- /dev/null
+++ b/_build/html/_sources/src/rust/lqosd/README.md.txt
@@ -0,0 +1,66 @@
+# LQOSD
+
+**The LibreQoS Daemon** is designed to run as a `systemd` service at all times. It provides:
+
+* Load/Unload the XDP/TC programs (they unload when the program exits)
+* Configure XDP/TC, based on the content of `/etc/lqos.conf`.
+ * Includes support for "on a stick" mode, using `OnAStick = True, StickVlanA = 1, StickVlanB = 2`.
+* Hosts a lightweight server offering "bus" queries for clients (such as `lqtop` and `xdp_iphash_to_cpu_cmdline`).
+ * See the `lqos_bus` sub-project for bus details.
+* Periodically gathers statistics for distribution to other systems via the bus.
+
+## Required Configuration
+
+You *must* have a file present called `/etc/lqos.conf`. At a minimum, it must tell `lqosd` where to find the LibreQoS configuration. For example:
+
+```toml
+lqos_directory = '/opt/libreqos'
+```
+
+## Offload Tuning
+
+`lqosd` can set kernel tunables for you on start-up. These are specified in `/etc/lqos.conf` also, in the `[tuning]` section:
+
+```toml
+[tuning]
+stop_irq_balance = true
+netdev_budget_usecs = 20
+netdev_budget_packets = 1
+rx_usecs = 0
+tx_usecs = 0
+disable_rxvlan = true
+disable_txvlan = true
+disable_offload = [ "gso", "tso", "lro", "sg", "gro" ]
+```
+
+> If this section is not present, no tuning will be performed.
+
+## Bifrost - eBPF Kernel Bridge
+
+To enable the kernel-side eBPF bridge, edit `/etc/lqos.conf`:
+
+```toml
+[bridge]
+use_xdp_bridge = true
+interface_mapping = [
+ { name = "eth1", redirect_to = "eth2", scan_vlans = false },
+ { name = "eth2", redirect_to = "eth1", scan_vlans = false }
+]
+vlan_mapping = []
+```
+
+Each interface must be a *physical* interface, not a VLAN. If you set `scan_vlans` to `true`, you can specify mapping rules.
+
+```toml
+[bridge]
+use_xdp_bridge = true
+interface_mapping = [
+ { name = "eth1", redirect_to = "eth1", scan_vlans = true },
+]
+vlan_mapping = [
+ { parent = "eth1", tag = 3, redirect_to = 4 },
+ { parent = "eth1", tag = 4, redirect_to = 3 },
+]
+```
+
+Reciprocal mappings are created NOT automatically, you have to specify each mapping. When you are using "on a stick" mode, you need to redirect to the same interface.
diff --git a/_build/html/_sources/src/rust/lqosd/src/node_manager/js_build/README.md.txt b/_build/html/_sources/src/rust/lqosd/src/node_manager/js_build/README.md.txt
new file mode 100644
index 00000000..252dbbbe
--- /dev/null
+++ b/_build/html/_sources/src/rust/lqosd/src/node_manager/js_build/README.md.txt
@@ -0,0 +1,5 @@
+# Site_build
+
+This assembles the JavaScript for the site using `esbuild`. You need to have installed
+`esbuild` with `sudo apt install esbuild` for this to work.
+
diff --git a/_build/html/_sources/src/rust/lqosd/src/node_manager/js_build/src/lq_js_common/README.md.txt b/_build/html/_sources/src/rust/lqosd/src/node_manager/js_build/src/lq_js_common/README.md.txt
new file mode 100644
index 00000000..57a28cf7
--- /dev/null
+++ b/_build/html/_sources/src/rust/lqosd/src/node_manager/js_build/src/lq_js_common/README.md.txt
@@ -0,0 +1,10 @@
+# LQHelper
+
+This provides a common JavaScript library used by various internal and external portions
+of LibreQOS. Like LibreQoS, it is GNU General Purpose License v2 for distribution.
+
+This project is licensed under the GNU General Public License v2.0 (GPL-2.0).
+However, we explicitly exempt other projects developed by LibreQoS from the copyleft requirements of the GPL-2.0, permitting their use of this project’s code under more permissive terms.
+
+Any contributors to this project (but not any forks or adaptations for other projects)
+**must** assign copyright to LibreQoS and retain these exemptions.
\ No newline at end of file
diff --git a/_build/html/_sources/src/rust/xdp_iphash_to_cpu_cmdline/README.md.txt b/_build/html/_sources/src/rust/xdp_iphash_to_cpu_cmdline/README.md.txt
new file mode 100644
index 00000000..cbce10cb
--- /dev/null
+++ b/_build/html/_sources/src/rust/xdp_iphash_to_cpu_cmdline/README.md.txt
@@ -0,0 +1,25 @@
+Note that this is *almost* compatible with the previous version. The syntax has changed so that the command must go first, and doesn't require a `--`.
+
+```
+Usage: xdp_iphash_to_cpu_cmdline [COMMAND]
+
+Commands:
+ add Add an IP Address (v4 or v6) to the XDP/TC mapping system
+ del Remove an IP address (v4 or v6) from the XDP/TC mapping system
+ clear Clear all mapped IPs
+ list List all mapped IPs
+ help Print this message or the help of the given subcommand(s)
+
+Options:
+ -h, --help Print help information
+```
+
+Examples:
+
+```
+xdp_iphash_to_cpu_cmdline list
+xdp_iphash_to_cpu_cmdline add --ip 192.168.100.1 --classid 5:3 --cpu 4
+xdp_iphash_to_cpu_cmdline add --ip 192.168.100.1 --classid 5:3 --cpu 4 --circuit-id CIRCUIT123 --device-id DEVICE456
+xdp_iphash_to_cpu_cmdline del 192.168.100.1
+xdp_iphash_to_cpu_cmdline clear
+```
diff --git a/_build/html/_static/_sphinx_javascript_frameworks_compat.js b/_build/html/_static/_sphinx_javascript_frameworks_compat.js
new file mode 100644
index 00000000..81415803
--- /dev/null
+++ b/_build/html/_static/_sphinx_javascript_frameworks_compat.js
@@ -0,0 +1,123 @@
+/* Compatability shim for jQuery and underscores.js.
+ *
+ * Copyright Sphinx contributors
+ * Released under the two clause BSD licence
+ */
+
+/**
+ * small helper function to urldecode strings
+ *
+ * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL
+ */
+jQuery.urldecode = function(x) {
+ if (!x) {
+ return x
+ }
+ return decodeURIComponent(x.replace(/\+/g, ' '));
+};
+
+/**
+ * small helper function to urlencode strings
+ */
+jQuery.urlencode = encodeURIComponent;
+
+/**
+ * This function returns the parsed url parameters of the
+ * current request. Multiple values per key are supported,
+ * it will always return arrays of strings for the value parts.
+ */
+jQuery.getQueryParameters = function(s) {
+ if (typeof s === 'undefined')
+ s = document.location.search;
+ var parts = s.substr(s.indexOf('?') + 1).split('&');
+ var result = {};
+ for (var i = 0; i < parts.length; i++) {
+ var tmp = parts[i].split('=', 2);
+ var key = jQuery.urldecode(tmp[0]);
+ var value = jQuery.urldecode(tmp[1]);
+ if (key in result)
+ result[key].push(value);
+ else
+ result[key] = [value];
+ }
+ return result;
+};
+
+/**
+ * highlight a given string on a jquery object by wrapping it in
+ * span elements with the given class name.
+ */
+jQuery.fn.highlightText = function(text, className) {
+ function highlight(node, addItems) {
+ if (node.nodeType === 3) {
+ var val = node.nodeValue;
+ var pos = val.toLowerCase().indexOf(text);
+ if (pos >= 0 &&
+ !jQuery(node.parentNode).hasClass(className) &&
+ !jQuery(node.parentNode).hasClass("nohighlight")) {
+ var span;
+ var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
+ if (isInSVG) {
+ span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
+ } else {
+ span = document.createElement("span");
+ span.className = className;
+ }
+ span.appendChild(document.createTextNode(val.substr(pos, text.length)));
+ node.parentNode.insertBefore(span, node.parentNode.insertBefore(
+ document.createTextNode(val.substr(pos + text.length)),
+ node.nextSibling));
+ node.nodeValue = val.substr(0, pos);
+ if (isInSVG) {
+ var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
+ var bbox = node.parentElement.getBBox();
+ rect.x.baseVal.value = bbox.x;
+ rect.y.baseVal.value = bbox.y;
+ rect.width.baseVal.value = bbox.width;
+ rect.height.baseVal.value = bbox.height;
+ rect.setAttribute('class', className);
+ addItems.push({
+ "parent": node.parentNode,
+ "target": rect});
+ }
+ }
+ }
+ else if (!jQuery(node).is("button, select, textarea")) {
+ jQuery.each(node.childNodes, function() {
+ highlight(this, addItems);
+ });
+ }
+ }
+ var addItems = [];
+ var result = this.each(function() {
+ highlight(this, addItems);
+ });
+ for (var i = 0; i < addItems.length; ++i) {
+ jQuery(addItems[i].parent).before(addItems[i].target);
+ }
+ return result;
+};
+
+/*
+ * backward compatibility for jQuery.browser
+ * This will be supported until firefox bug is fixed.
+ */
+if (!jQuery.browser) {
+ jQuery.uaMatch = function(ua) {
+ ua = ua.toLowerCase();
+
+ var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
+ /(webkit)[ \/]([\w.]+)/.exec(ua) ||
+ /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
+ /(msie) ([\w.]+)/.exec(ua) ||
+ ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
+ [];
+
+ return {
+ browser: match[ 1 ] || "",
+ version: match[ 2 ] || "0"
+ };
+ };
+ jQuery.browser = {};
+ jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
+}
diff --git a/_build/html/_static/basic.css b/_build/html/_static/basic.css
new file mode 100644
index 00000000..7577acb1
--- /dev/null
+++ b/_build/html/_static/basic.css
@@ -0,0 +1,903 @@
+/*
+ * basic.css
+ * ~~~~~~~~~
+ *
+ * Sphinx stylesheet -- basic theme.
+ *
+ * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+/* -- main layout ----------------------------------------------------------- */
+
+div.clearer {
+ clear: both;
+}
+
+div.section::after {
+ display: block;
+ content: '';
+ clear: left;
+}
+
+/* -- relbar ---------------------------------------------------------------- */
+
+div.related {
+ width: 100%;
+ font-size: 90%;
+}
+
+div.related h3 {
+ display: none;
+}
+
+div.related ul {
+ margin: 0;
+ padding: 0 0 0 10px;
+ list-style: none;
+}
+
+div.related li {
+ display: inline;
+}
+
+div.related li.right {
+ float: right;
+ margin-right: 5px;
+}
+
+/* -- sidebar --------------------------------------------------------------- */
+
+div.sphinxsidebarwrapper {
+ padding: 10px 5px 0 10px;
+}
+
+div.sphinxsidebar {
+ float: left;
+ width: 230px;
+ margin-left: -100%;
+ font-size: 90%;
+ word-wrap: break-word;
+ overflow-wrap : break-word;
+}
+
+div.sphinxsidebar ul {
+ list-style: none;
+}
+
+div.sphinxsidebar ul ul,
+div.sphinxsidebar ul.want-points {
+ margin-left: 20px;
+ list-style: square;
+}
+
+div.sphinxsidebar ul ul {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+div.sphinxsidebar form {
+ margin-top: 10px;
+}
+
+div.sphinxsidebar input {
+ border: 1px solid #98dbcc;
+ font-family: sans-serif;
+ font-size: 1em;
+}
+
+div.sphinxsidebar #searchbox form.search {
+ overflow: hidden;
+}
+
+div.sphinxsidebar #searchbox input[type="text"] {
+ float: left;
+ width: 80%;
+ padding: 0.25em;
+ box-sizing: border-box;
+}
+
+div.sphinxsidebar #searchbox input[type="submit"] {
+ float: left;
+ width: 20%;
+ border-left: none;
+ padding: 0.25em;
+ box-sizing: border-box;
+}
+
+
+img {
+ border: 0;
+ max-width: 100%;
+}
+
+/* -- search page ----------------------------------------------------------- */
+
+ul.search {
+ margin: 10px 0 0 20px;
+ padding: 0;
+}
+
+ul.search li {
+ padding: 5px 0 5px 20px;
+ background-image: url(file.png);
+ background-repeat: no-repeat;
+ background-position: 0 7px;
+}
+
+ul.search li a {
+ font-weight: bold;
+}
+
+ul.search li p.context {
+ color: #888;
+ margin: 2px 0 0 30px;
+ text-align: left;
+}
+
+ul.keywordmatches li.goodmatch a {
+ font-weight: bold;
+}
+
+/* -- index page ------------------------------------------------------------ */
+
+table.contentstable {
+ width: 90%;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+table.contentstable p.biglink {
+ line-height: 150%;
+}
+
+a.biglink {
+ font-size: 1.3em;
+}
+
+span.linkdescr {
+ font-style: italic;
+ padding-top: 5px;
+ font-size: 90%;
+}
+
+/* -- general index --------------------------------------------------------- */
+
+table.indextable {
+ width: 100%;
+}
+
+table.indextable td {
+ text-align: left;
+ vertical-align: top;
+}
+
+table.indextable ul {
+ margin-top: 0;
+ margin-bottom: 0;
+ list-style-type: none;
+}
+
+table.indextable > tbody > tr > td > ul {
+ padding-left: 0em;
+}
+
+table.indextable tr.pcap {
+ height: 10px;
+}
+
+table.indextable tr.cap {
+ margin-top: 10px;
+ background-color: #f2f2f2;
+}
+
+img.toggler {
+ margin-right: 3px;
+ margin-top: 3px;
+ cursor: pointer;
+}
+
+div.modindex-jumpbox {
+ border-top: 1px solid #ddd;
+ border-bottom: 1px solid #ddd;
+ margin: 1em 0 1em 0;
+ padding: 0.4em;
+}
+
+div.genindex-jumpbox {
+ border-top: 1px solid #ddd;
+ border-bottom: 1px solid #ddd;
+ margin: 1em 0 1em 0;
+ padding: 0.4em;
+}
+
+/* -- domain module index --------------------------------------------------- */
+
+table.modindextable td {
+ padding: 2px;
+ border-collapse: collapse;
+}
+
+/* -- general body styles --------------------------------------------------- */
+
+div.body {
+ min-width: 360px;
+ max-width: 800px;
+}
+
+div.body p, div.body dd, div.body li, div.body blockquote {
+ -moz-hyphens: auto;
+ -ms-hyphens: auto;
+ -webkit-hyphens: auto;
+ hyphens: auto;
+}
+
+a.headerlink {
+ visibility: hidden;
+}
+
+h1:hover > a.headerlink,
+h2:hover > a.headerlink,
+h3:hover > a.headerlink,
+h4:hover > a.headerlink,
+h5:hover > a.headerlink,
+h6:hover > a.headerlink,
+dt:hover > a.headerlink,
+caption:hover > a.headerlink,
+p.caption:hover > a.headerlink,
+div.code-block-caption:hover > a.headerlink {
+ visibility: visible;
+}
+
+div.body p.caption {
+ text-align: inherit;
+}
+
+div.body td {
+ text-align: left;
+}
+
+.first {
+ margin-top: 0 !important;
+}
+
+p.rubric {
+ margin-top: 30px;
+ font-weight: bold;
+}
+
+img.align-left, figure.align-left, .figure.align-left, object.align-left {
+ clear: left;
+ float: left;
+ margin-right: 1em;
+}
+
+img.align-right, figure.align-right, .figure.align-right, object.align-right {
+ clear: right;
+ float: right;
+ margin-left: 1em;
+}
+
+img.align-center, figure.align-center, .figure.align-center, object.align-center {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+img.align-default, figure.align-default, .figure.align-default {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.align-left {
+ text-align: left;
+}
+
+.align-center {
+ text-align: center;
+}
+
+.align-default {
+ text-align: center;
+}
+
+.align-right {
+ text-align: right;
+}
+
+/* -- sidebars -------------------------------------------------------------- */
+
+div.sidebar,
+aside.sidebar {
+ margin: 0 0 0.5em 1em;
+ border: 1px solid #ddb;
+ padding: 7px;
+ background-color: #ffe;
+ width: 40%;
+ float: right;
+ clear: right;
+ overflow-x: auto;
+}
+
+p.sidebar-title {
+ font-weight: bold;
+}
+
+nav.contents,
+aside.topic,
+div.admonition, div.topic, blockquote {
+ clear: left;
+}
+
+/* -- topics ---------------------------------------------------------------- */
+
+nav.contents,
+aside.topic,
+div.topic {
+ border: 1px solid #ccc;
+ padding: 7px;
+ margin: 10px 0 10px 0;
+}
+
+p.topic-title {
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 10px;
+}
+
+/* -- admonitions ----------------------------------------------------------- */
+
+div.admonition {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ padding: 7px;
+}
+
+div.admonition dt {
+ font-weight: bold;
+}
+
+p.admonition-title {
+ margin: 0px 10px 5px 0px;
+ font-weight: bold;
+}
+
+div.body p.centered {
+ text-align: center;
+ margin-top: 25px;
+}
+
+/* -- content of sidebars/topics/admonitions -------------------------------- */
+
+div.sidebar > :last-child,
+aside.sidebar > :last-child,
+nav.contents > :last-child,
+aside.topic > :last-child,
+div.topic > :last-child,
+div.admonition > :last-child {
+ margin-bottom: 0;
+}
+
+div.sidebar::after,
+aside.sidebar::after,
+nav.contents::after,
+aside.topic::after,
+div.topic::after,
+div.admonition::after,
+blockquote::after {
+ display: block;
+ content: '';
+ clear: both;
+}
+
+/* -- tables ---------------------------------------------------------------- */
+
+table.docutils {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ border: 0;
+ border-collapse: collapse;
+}
+
+table.align-center {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+table.align-default {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+table caption span.caption-number {
+ font-style: italic;
+}
+
+table caption span.caption-text {
+}
+
+table.docutils td, table.docutils th {
+ padding: 1px 8px 1px 5px;
+ border-top: 0;
+ border-left: 0;
+ border-right: 0;
+ border-bottom: 1px solid #aaa;
+}
+
+th {
+ text-align: left;
+ padding-right: 5px;
+}
+
+table.citation {
+ border-left: solid 1px gray;
+ margin-left: 1px;
+}
+
+table.citation td {
+ border-bottom: none;
+}
+
+th > :first-child,
+td > :first-child {
+ margin-top: 0px;
+}
+
+th > :last-child,
+td > :last-child {
+ margin-bottom: 0px;
+}
+
+/* -- figures --------------------------------------------------------------- */
+
+div.figure, figure {
+ margin: 0.5em;
+ padding: 0.5em;
+}
+
+div.figure p.caption, figcaption {
+ padding: 0.3em;
+}
+
+div.figure p.caption span.caption-number,
+figcaption span.caption-number {
+ font-style: italic;
+}
+
+div.figure p.caption span.caption-text,
+figcaption span.caption-text {
+}
+
+/* -- field list styles ----------------------------------------------------- */
+
+table.field-list td, table.field-list th {
+ border: 0 !important;
+}
+
+.field-list ul {
+ margin: 0;
+ padding-left: 1em;
+}
+
+.field-list p {
+ margin: 0;
+}
+
+.field-name {
+ -moz-hyphens: manual;
+ -ms-hyphens: manual;
+ -webkit-hyphens: manual;
+ hyphens: manual;
+}
+
+/* -- hlist styles ---------------------------------------------------------- */
+
+table.hlist {
+ margin: 1em 0;
+}
+
+table.hlist td {
+ vertical-align: top;
+}
+
+/* -- object description styles --------------------------------------------- */
+
+.sig {
+ font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
+}
+
+.sig-name, code.descname {
+ background-color: transparent;
+ font-weight: bold;
+}
+
+.sig-name {
+ font-size: 1.1em;
+}
+
+code.descname {
+ font-size: 1.2em;
+}
+
+.sig-prename, code.descclassname {
+ background-color: transparent;
+}
+
+.optional {
+ font-size: 1.3em;
+}
+
+.sig-paren {
+ font-size: larger;
+}
+
+.sig-param.n {
+ font-style: italic;
+}
+
+/* C++ specific styling */
+
+.sig-inline.c-texpr,
+.sig-inline.cpp-texpr {
+ font-family: unset;
+}
+
+.sig.c .k, .sig.c .kt,
+.sig.cpp .k, .sig.cpp .kt {
+ color: #0033B3;
+}
+
+.sig.c .m,
+.sig.cpp .m {
+ color: #1750EB;
+}
+
+.sig.c .s, .sig.c .sc,
+.sig.cpp .s, .sig.cpp .sc {
+ color: #067D17;
+}
+
+
+/* -- other body styles ----------------------------------------------------- */
+
+ol.arabic {
+ list-style: decimal;
+}
+
+ol.loweralpha {
+ list-style: lower-alpha;
+}
+
+ol.upperalpha {
+ list-style: upper-alpha;
+}
+
+ol.lowerroman {
+ list-style: lower-roman;
+}
+
+ol.upperroman {
+ list-style: upper-roman;
+}
+
+:not(li) > ol > li:first-child > :first-child,
+:not(li) > ul > li:first-child > :first-child {
+ margin-top: 0px;
+}
+
+:not(li) > ol > li:last-child > :last-child,
+:not(li) > ul > li:last-child > :last-child {
+ margin-bottom: 0px;
+}
+
+ol.simple ol p,
+ol.simple ul p,
+ul.simple ol p,
+ul.simple ul p {
+ margin-top: 0;
+}
+
+ol.simple > li:not(:first-child) > p,
+ul.simple > li:not(:first-child) > p {
+ margin-top: 0;
+}
+
+ol.simple p,
+ul.simple p {
+ margin-bottom: 0;
+}
+
+aside.footnote > span,
+div.citation > span {
+ float: left;
+}
+aside.footnote > span:last-of-type,
+div.citation > span:last-of-type {
+ padding-right: 0.5em;
+}
+aside.footnote > p {
+ margin-left: 2em;
+}
+div.citation > p {
+ margin-left: 4em;
+}
+aside.footnote > p:last-of-type,
+div.citation > p:last-of-type {
+ margin-bottom: 0em;
+}
+aside.footnote > p:last-of-type:after,
+div.citation > p:last-of-type:after {
+ content: "";
+ clear: both;
+}
+
+dl.field-list {
+ display: grid;
+ grid-template-columns: fit-content(30%) auto;
+}
+
+dl.field-list > dt {
+ font-weight: bold;
+ word-break: break-word;
+ padding-left: 0.5em;
+ padding-right: 5px;
+}
+
+dl.field-list > dd {
+ padding-left: 0.5em;
+ margin-top: 0em;
+ margin-left: 0em;
+ margin-bottom: 0em;
+}
+
+dl {
+ margin-bottom: 15px;
+}
+
+dd > :first-child {
+ margin-top: 0px;
+}
+
+dd ul, dd table {
+ margin-bottom: 10px;
+}
+
+dd {
+ margin-top: 3px;
+ margin-bottom: 10px;
+ margin-left: 30px;
+}
+
+dl > dd:last-child,
+dl > dd:last-child > :last-child {
+ margin-bottom: 0;
+}
+
+dt:target, span.highlighted {
+ background-color: #fbe54e;
+}
+
+rect.highlighted {
+ fill: #fbe54e;
+}
+
+dl.glossary dt {
+ font-weight: bold;
+ font-size: 1.1em;
+}
+
+.versionmodified {
+ font-style: italic;
+}
+
+.system-message {
+ background-color: #fda;
+ padding: 5px;
+ border: 3px solid red;
+}
+
+.footnote:target {
+ background-color: #ffa;
+}
+
+.line-block {
+ display: block;
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+
+.line-block .line-block {
+ margin-top: 0;
+ margin-bottom: 0;
+ margin-left: 1.5em;
+}
+
+.guilabel, .menuselection {
+ font-family: sans-serif;
+}
+
+.accelerator {
+ text-decoration: underline;
+}
+
+.classifier {
+ font-style: oblique;
+}
+
+.classifier:before {
+ font-style: normal;
+ margin: 0 0.5em;
+ content: ":";
+ display: inline-block;
+}
+
+abbr, acronym {
+ border-bottom: dotted 1px;
+ cursor: help;
+}
+
+/* -- code displays --------------------------------------------------------- */
+
+pre {
+ overflow: auto;
+ overflow-y: hidden; /* fixes display issues on Chrome browsers */
+}
+
+pre, div[class*="highlight-"] {
+ clear: both;
+}
+
+span.pre {
+ -moz-hyphens: none;
+ -ms-hyphens: none;
+ -webkit-hyphens: none;
+ hyphens: none;
+ white-space: nowrap;
+}
+
+div[class*="highlight-"] {
+ margin: 1em 0;
+}
+
+td.linenos pre {
+ border: 0;
+ background-color: transparent;
+ color: #aaa;
+}
+
+table.highlighttable {
+ display: block;
+}
+
+table.highlighttable tbody {
+ display: block;
+}
+
+table.highlighttable tr {
+ display: flex;
+}
+
+table.highlighttable td {
+ margin: 0;
+ padding: 0;
+}
+
+table.highlighttable td.linenos {
+ padding-right: 0.5em;
+}
+
+table.highlighttable td.code {
+ flex: 1;
+ overflow: hidden;
+}
+
+.highlight .hll {
+ display: block;
+}
+
+div.highlight pre,
+table.highlighttable pre {
+ margin: 0;
+}
+
+div.code-block-caption + div {
+ margin-top: 0;
+}
+
+div.code-block-caption {
+ margin-top: 1em;
+ padding: 2px 5px;
+ font-size: small;
+}
+
+div.code-block-caption code {
+ background-color: transparent;
+}
+
+table.highlighttable td.linenos,
+span.linenos,
+div.highlight span.gp { /* gp: Generic.Prompt */
+ user-select: none;
+ -webkit-user-select: text; /* Safari fallback only */
+ -webkit-user-select: none; /* Chrome/Safari */
+ -moz-user-select: none; /* Firefox */
+ -ms-user-select: none; /* IE10+ */
+}
+
+div.code-block-caption span.caption-number {
+ padding: 0.1em 0.3em;
+ font-style: italic;
+}
+
+div.code-block-caption span.caption-text {
+}
+
+div.literal-block-wrapper {
+ margin: 1em 0;
+}
+
+code.xref, a code {
+ background-color: transparent;
+ font-weight: bold;
+}
+
+h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
+ background-color: transparent;
+}
+
+.viewcode-link {
+ float: right;
+}
+
+.viewcode-back {
+ float: right;
+ font-family: sans-serif;
+}
+
+div.viewcode-block:target {
+ margin: -1px -10px;
+ padding: 0 10px;
+}
+
+/* -- math display ---------------------------------------------------------- */
+
+img.math {
+ vertical-align: middle;
+}
+
+div.body div.math p {
+ text-align: center;
+}
+
+span.eqno {
+ float: right;
+}
+
+span.eqno a.headerlink {
+ position: absolute;
+ z-index: 1;
+}
+
+div.math:hover a.headerlink {
+ visibility: visible;
+}
+
+/* -- printout stylesheet --------------------------------------------------- */
+
+@media print {
+ div.document,
+ div.documentwrapper,
+ div.bodywrapper {
+ margin: 0 !important;
+ width: 100%;
+ }
+
+ div.sphinxsidebar,
+ div.related,
+ div.footer,
+ #top-link {
+ display: none;
+ }
+}
\ No newline at end of file
diff --git a/_build/html/_static/css/badge_only.css b/_build/html/_static/css/badge_only.css
new file mode 100644
index 00000000..88ba55b9
--- /dev/null
+++ b/_build/html/_static/css/badge_only.css
@@ -0,0 +1 @@
+.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions .rst-other-versions .rtd-current-item{font-weight:700}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}#flyout-search-form{padding:6px}
\ No newline at end of file
diff --git a/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff b/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff
new file mode 100644
index 00000000..6cb60000
Binary files /dev/null and b/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff differ
diff --git a/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff2 b/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff2
new file mode 100644
index 00000000..7059e231
Binary files /dev/null and b/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff2 differ
diff --git a/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff b/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff
new file mode 100644
index 00000000..f815f63f
Binary files /dev/null and b/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff differ
diff --git a/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff2 b/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff2
new file mode 100644
index 00000000..f2c76e5b
Binary files /dev/null and b/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff2 differ
diff --git a/_build/html/_static/css/fonts/fontawesome-webfont.eot b/_build/html/_static/css/fonts/fontawesome-webfont.eot
new file mode 100644
index 00000000..e9f60ca9
Binary files /dev/null and b/_build/html/_static/css/fonts/fontawesome-webfont.eot differ
diff --git a/_build/html/_static/css/fonts/fontawesome-webfont.svg b/_build/html/_static/css/fonts/fontawesome-webfont.svg
new file mode 100644
index 00000000..855c845e
--- /dev/null
+++ b/_build/html/_static/css/fonts/fontawesome-webfont.svg
@@ -0,0 +1,2671 @@
+
+
+
diff --git a/_build/html/_static/css/fonts/fontawesome-webfont.ttf b/_build/html/_static/css/fonts/fontawesome-webfont.ttf
new file mode 100644
index 00000000..35acda2f
Binary files /dev/null and b/_build/html/_static/css/fonts/fontawesome-webfont.ttf differ
diff --git a/_build/html/_static/css/fonts/fontawesome-webfont.woff b/_build/html/_static/css/fonts/fontawesome-webfont.woff
new file mode 100644
index 00000000..400014a4
Binary files /dev/null and b/_build/html/_static/css/fonts/fontawesome-webfont.woff differ
diff --git a/_build/html/_static/css/fonts/fontawesome-webfont.woff2 b/_build/html/_static/css/fonts/fontawesome-webfont.woff2
new file mode 100644
index 00000000..4d13fc60
Binary files /dev/null and b/_build/html/_static/css/fonts/fontawesome-webfont.woff2 differ
diff --git a/_build/html/_static/css/fonts/lato-bold-italic.woff b/_build/html/_static/css/fonts/lato-bold-italic.woff
new file mode 100644
index 00000000..88ad05b9
Binary files /dev/null and b/_build/html/_static/css/fonts/lato-bold-italic.woff differ
diff --git a/_build/html/_static/css/fonts/lato-bold-italic.woff2 b/_build/html/_static/css/fonts/lato-bold-italic.woff2
new file mode 100644
index 00000000..c4e3d804
Binary files /dev/null and b/_build/html/_static/css/fonts/lato-bold-italic.woff2 differ
diff --git a/_build/html/_static/css/fonts/lato-bold.woff b/_build/html/_static/css/fonts/lato-bold.woff
new file mode 100644
index 00000000..c6dff51f
Binary files /dev/null and b/_build/html/_static/css/fonts/lato-bold.woff differ
diff --git a/_build/html/_static/css/fonts/lato-bold.woff2 b/_build/html/_static/css/fonts/lato-bold.woff2
new file mode 100644
index 00000000..bb195043
Binary files /dev/null and b/_build/html/_static/css/fonts/lato-bold.woff2 differ
diff --git a/_build/html/_static/css/fonts/lato-normal-italic.woff b/_build/html/_static/css/fonts/lato-normal-italic.woff
new file mode 100644
index 00000000..76114bc0
Binary files /dev/null and b/_build/html/_static/css/fonts/lato-normal-italic.woff differ
diff --git a/_build/html/_static/css/fonts/lato-normal-italic.woff2 b/_build/html/_static/css/fonts/lato-normal-italic.woff2
new file mode 100644
index 00000000..3404f37e
Binary files /dev/null and b/_build/html/_static/css/fonts/lato-normal-italic.woff2 differ
diff --git a/_build/html/_static/css/fonts/lato-normal.woff b/_build/html/_static/css/fonts/lato-normal.woff
new file mode 100644
index 00000000..ae1307ff
Binary files /dev/null and b/_build/html/_static/css/fonts/lato-normal.woff differ
diff --git a/_build/html/_static/css/fonts/lato-normal.woff2 b/_build/html/_static/css/fonts/lato-normal.woff2
new file mode 100644
index 00000000..3bf98433
Binary files /dev/null and b/_build/html/_static/css/fonts/lato-normal.woff2 differ
diff --git a/_build/html/_static/css/theme.css b/_build/html/_static/css/theme.css
new file mode 100644
index 00000000..a88467c1
--- /dev/null
+++ b/_build/html/_static/css/theme.css
@@ -0,0 +1,4 @@
+html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden],audio:not([controls]){display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;text-decoration:none}ins,mark{color:#000}mark{background:#ff0;font-style:italic;font-weight:700}.rst-content code,.rst-content tt,code,kbd,pre,samp{font-family:monospace,serif;_font-family:courier new,monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:after,q:before{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,ol,ul{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure,form{margin:0}label{cursor:pointer}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}textarea{resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{body,html,section{background:none!important}*{box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}.rst-content .toctree-wrapper>p.caption,h2,h3,p{orphans:3;widows:3}.rst-content .toctree-wrapper>p.caption,h2,h3{page-break-after:avoid}}.btn,.fa:before,.icon:before,.rst-content .admonition,.rst-content .admonition-title:before,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .code-block-caption .headerlink:before,.rst-content .danger,.rst-content .eqno .headerlink:before,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-alert,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}/*!
+ * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
+ * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
+ */@font-face{font-family:FontAwesome;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix&v=4.7.0) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa-pull-left.icon,.fa.fa-pull-left,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content .eqno .fa-pull-left.headerlink,.rst-content .fa-pull-left.admonition-title,.rst-content code.download span.fa-pull-left:first-child,.rst-content dl dt .fa-pull-left.headerlink,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content p .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.wy-menu-vertical li.current>a button.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-left.toctree-expand,.wy-menu-vertical li button.fa-pull-left.toctree-expand{margin-right:.3em}.fa-pull-right.icon,.fa.fa-pull-right,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content .eqno .fa-pull-right.headerlink,.rst-content .fa-pull-right.admonition-title,.rst-content code.download span.fa-pull-right:first-child,.rst-content dl dt .fa-pull-right.headerlink,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content p .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.wy-menu-vertical li.current>a button.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-right.toctree-expand,.wy-menu-vertical li button.fa-pull-right.toctree-expand{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.pull-left.icon,.rst-content .code-block-caption .pull-left.headerlink,.rst-content .eqno .pull-left.headerlink,.rst-content .pull-left.admonition-title,.rst-content code.download span.pull-left:first-child,.rst-content dl dt .pull-left.headerlink,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content p .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.wy-menu-vertical li.current>a button.pull-left.toctree-expand,.wy-menu-vertical li.on a button.pull-left.toctree-expand,.wy-menu-vertical li button.pull-left.toctree-expand{margin-right:.3em}.fa.pull-right,.pull-right.icon,.rst-content .code-block-caption .pull-right.headerlink,.rst-content .eqno .pull-right.headerlink,.rst-content .pull-right.admonition-title,.rst-content code.download span.pull-right:first-child,.rst-content dl dt .pull-right.headerlink,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content p .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.wy-menu-vertical li.current>a button.pull-right.toctree-expand,.wy-menu-vertical li.on a button.pull-right.toctree-expand,.wy-menu-vertical li button.pull-right.toctree-expand{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.rst-content .admonition-title:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.icon-caret-down:before,.wy-dropdown .caret:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li button.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-bed:before,.fa-hotel:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-y-combinator:before,.fa-yc:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-television:before,.fa-tv:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:""}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-sign-language:before,.fa-signing:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-address-card:before,.fa-vcard:before{content:""}.fa-address-card-o:before,.fa-vcard-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{font-family:inherit}.fa:before,.icon:before,.rst-content .admonition-title:before,.rst-content .code-block-caption .headerlink:before,.rst-content .eqno .headerlink:before,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before{font-family:FontAwesome;display:inline-block;font-style:normal;font-weight:400;line-height:1;text-decoration:inherit}.rst-content .code-block-caption a .headerlink,.rst-content .eqno a .headerlink,.rst-content a .admonition-title,.rst-content code.download a span:first-child,.rst-content dl dt a .headerlink,.rst-content h1 a .headerlink,.rst-content h2 a .headerlink,.rst-content h3 a .headerlink,.rst-content h4 a .headerlink,.rst-content h5 a .headerlink,.rst-content h6 a .headerlink,.rst-content p.caption a .headerlink,.rst-content p a .headerlink,.rst-content table>caption a .headerlink,.rst-content tt.download a span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li a button.toctree-expand,a .fa,a .icon,a .rst-content .admonition-title,a .rst-content .code-block-caption .headerlink,a .rst-content .eqno .headerlink,a .rst-content code.download span:first-child,a .rst-content dl dt .headerlink,a .rst-content h1 .headerlink,a .rst-content h2 .headerlink,a .rst-content h3 .headerlink,a .rst-content h4 .headerlink,a .rst-content h5 .headerlink,a .rst-content h6 .headerlink,a .rst-content p.caption .headerlink,a .rst-content p .headerlink,a .rst-content table>caption .headerlink,a .rst-content tt.download span:first-child,a .wy-menu-vertical li button.toctree-expand{display:inline-block;text-decoration:inherit}.btn .fa,.btn .icon,.btn .rst-content .admonition-title,.btn .rst-content .code-block-caption .headerlink,.btn .rst-content .eqno .headerlink,.btn .rst-content code.download span:first-child,.btn .rst-content dl dt .headerlink,.btn .rst-content h1 .headerlink,.btn .rst-content h2 .headerlink,.btn .rst-content h3 .headerlink,.btn .rst-content h4 .headerlink,.btn .rst-content h5 .headerlink,.btn .rst-content h6 .headerlink,.btn .rst-content p .headerlink,.btn .rst-content table>caption .headerlink,.btn .rst-content tt.download span:first-child,.btn .wy-menu-vertical li.current>a button.toctree-expand,.btn .wy-menu-vertical li.on a button.toctree-expand,.btn .wy-menu-vertical li button.toctree-expand,.nav .fa,.nav .icon,.nav .rst-content .admonition-title,.nav .rst-content .code-block-caption .headerlink,.nav .rst-content .eqno .headerlink,.nav .rst-content code.download span:first-child,.nav .rst-content dl dt .headerlink,.nav .rst-content h1 .headerlink,.nav .rst-content h2 .headerlink,.nav .rst-content h3 .headerlink,.nav .rst-content h4 .headerlink,.nav .rst-content h5 .headerlink,.nav .rst-content h6 .headerlink,.nav .rst-content p .headerlink,.nav .rst-content table>caption .headerlink,.nav .rst-content tt.download span:first-child,.nav .wy-menu-vertical li.current>a button.toctree-expand,.nav .wy-menu-vertical li.on a button.toctree-expand,.nav .wy-menu-vertical li button.toctree-expand,.rst-content .btn .admonition-title,.rst-content .code-block-caption .btn .headerlink,.rst-content .code-block-caption .nav .headerlink,.rst-content .eqno .btn .headerlink,.rst-content .eqno .nav .headerlink,.rst-content .nav .admonition-title,.rst-content code.download .btn span:first-child,.rst-content code.download .nav span:first-child,.rst-content dl dt .btn .headerlink,.rst-content dl dt .nav .headerlink,.rst-content h1 .btn .headerlink,.rst-content h1 .nav .headerlink,.rst-content h2 .btn .headerlink,.rst-content h2 .nav .headerlink,.rst-content h3 .btn .headerlink,.rst-content h3 .nav .headerlink,.rst-content h4 .btn .headerlink,.rst-content h4 .nav .headerlink,.rst-content h5 .btn .headerlink,.rst-content h5 .nav .headerlink,.rst-content h6 .btn .headerlink,.rst-content h6 .nav .headerlink,.rst-content p .btn .headerlink,.rst-content p .nav .headerlink,.rst-content table>caption .btn .headerlink,.rst-content table>caption .nav .headerlink,.rst-content tt.download .btn span:first-child,.rst-content tt.download .nav span:first-child,.wy-menu-vertical li .btn button.toctree-expand,.wy-menu-vertical li.current>a .btn button.toctree-expand,.wy-menu-vertical li.current>a .nav button.toctree-expand,.wy-menu-vertical li .nav button.toctree-expand,.wy-menu-vertical li.on a .btn button.toctree-expand,.wy-menu-vertical li.on a .nav button.toctree-expand{display:inline}.btn .fa-large.icon,.btn .fa.fa-large,.btn .rst-content .code-block-caption .fa-large.headerlink,.btn .rst-content .eqno .fa-large.headerlink,.btn .rst-content .fa-large.admonition-title,.btn .rst-content code.download span.fa-large:first-child,.btn .rst-content dl dt .fa-large.headerlink,.btn .rst-content h1 .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.btn .rst-content p .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.btn .wy-menu-vertical li button.fa-large.toctree-expand,.nav .fa-large.icon,.nav .fa.fa-large,.nav .rst-content .code-block-caption .fa-large.headerlink,.nav .rst-content .eqno .fa-large.headerlink,.nav .rst-content .fa-large.admonition-title,.nav .rst-content code.download span.fa-large:first-child,.nav .rst-content dl dt .fa-large.headerlink,.nav .rst-content h1 .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.nav .rst-content p .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.nav .wy-menu-vertical li button.fa-large.toctree-expand,.rst-content .btn .fa-large.admonition-title,.rst-content .code-block-caption .btn .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.rst-content .eqno .btn .fa-large.headerlink,.rst-content .eqno .nav .fa-large.headerlink,.rst-content .nav .fa-large.admonition-title,.rst-content code.download .btn span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.rst-content dl dt .btn .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.rst-content p .btn .fa-large.headerlink,.rst-content p .nav .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.rst-content tt.download .btn span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.wy-menu-vertical li .btn button.fa-large.toctree-expand,.wy-menu-vertical li .nav button.fa-large.toctree-expand{line-height:.9em}.btn .fa-spin.icon,.btn .fa.fa-spin,.btn .rst-content .code-block-caption .fa-spin.headerlink,.btn .rst-content .eqno .fa-spin.headerlink,.btn .rst-content .fa-spin.admonition-title,.btn .rst-content code.download span.fa-spin:first-child,.btn .rst-content dl dt .fa-spin.headerlink,.btn .rst-content h1 .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.btn .rst-content p .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.btn .wy-menu-vertical li button.fa-spin.toctree-expand,.nav .fa-spin.icon,.nav .fa.fa-spin,.nav .rst-content .code-block-caption .fa-spin.headerlink,.nav .rst-content .eqno .fa-spin.headerlink,.nav .rst-content .fa-spin.admonition-title,.nav .rst-content code.download span.fa-spin:first-child,.nav .rst-content dl dt .fa-spin.headerlink,.nav .rst-content h1 .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.nav .rst-content p .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.nav .wy-menu-vertical li button.fa-spin.toctree-expand,.rst-content .btn .fa-spin.admonition-title,.rst-content .code-block-caption .btn .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.rst-content .eqno .btn .fa-spin.headerlink,.rst-content .eqno .nav .fa-spin.headerlink,.rst-content .nav .fa-spin.admonition-title,.rst-content code.download .btn span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.rst-content dl dt .btn .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.rst-content p .btn .fa-spin.headerlink,.rst-content p .nav .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.rst-content tt.download .btn span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.wy-menu-vertical li .btn button.fa-spin.toctree-expand,.wy-menu-vertical li .nav button.fa-spin.toctree-expand{display:inline-block}.btn.fa:before,.btn.icon:before,.rst-content .btn.admonition-title:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content .eqno .btn.headerlink:before,.rst-content code.download span.btn:first-child:before,.rst-content dl dt .btn.headerlink:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content p .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.wy-menu-vertical li button.btn.toctree-expand:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.btn.icon:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content .eqno .btn.headerlink:hover:before,.rst-content code.download span.btn:first-child:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content p .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.wy-menu-vertical li button.btn.toctree-expand:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .icon:before,.btn-mini .rst-content .admonition-title:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.btn-mini .rst-content .eqno .headerlink:before,.btn-mini .rst-content code.download span:first-child:before,.btn-mini .rst-content dl dt .headerlink:before,.btn-mini .rst-content h1 .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.btn-mini .rst-content p .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.btn-mini .wy-menu-vertical li button.toctree-expand:before,.rst-content .btn-mini .admonition-title:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.rst-content .eqno .btn-mini .headerlink:before,.rst-content code.download .btn-mini span:first-child:before,.rst-content dl dt .btn-mini .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.rst-content p .btn-mini .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.rst-content tt.download .btn-mini span:first-child:before,.wy-menu-vertical li .btn-mini button.toctree-expand:before{font-size:14px;vertical-align:-15%}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.wy-alert{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.rst-content .admonition-title,.wy-alert-title{font-weight:700;display:block;color:#fff;background:#6ab0de;padding:6px 12px;margin:-12px -12px 12px}.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.admonition,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.wy-alert.wy-alert-danger{background:#fdf3f2}.rst-content .danger .admonition-title,.rst-content .danger .wy-alert-title,.rst-content .error .admonition-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .admonition-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.wy-alert.wy-alert-danger .wy-alert-title{background:#f29f97}.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .warning,.rst-content .wy-alert-warning.admonition,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.note,.rst-content .wy-alert-warning.seealso,.rst-content .wy-alert-warning.tip,.wy-alert.wy-alert-warning{background:#ffedcc}.rst-content .admonition-todo .admonition-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .attention .admonition-title,.rst-content .attention .wy-alert-title,.rst-content .caution .admonition-title,.rst-content .caution .wy-alert-title,.rst-content .warning .admonition-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.admonition .admonition-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.wy-alert.wy-alert-warning .wy-alert-title{background:#f0b37e}.rst-content .note,.rst-content .seealso,.rst-content .wy-alert-info.admonition,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.wy-alert.wy-alert-info{background:#e7f2fa}.rst-content .note .admonition-title,.rst-content .note .wy-alert-title,.rst-content .seealso .admonition-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .admonition-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.wy-alert.wy-alert-info .wy-alert-title{background:#6ab0de}.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.admonition,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.warning,.wy-alert.wy-alert-success{background:#dbfaf4}.rst-content .hint .admonition-title,.rst-content .hint .wy-alert-title,.rst-content .important .admonition-title,.rst-content .important .wy-alert-title,.rst-content .tip .admonition-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .admonition-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.wy-alert.wy-alert-success .wy-alert-title{background:#1abc9c}.rst-content .wy-alert-neutral.admonition,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.wy-alert.wy-alert-neutral{background:#f3f6f6}.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .admonition-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.wy-alert.wy-alert-neutral .wy-alert-title{color:#404040;background:#e1e4e5}.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.wy-alert.wy-alert-neutral a{color:#2980b9}.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .note p:last-child,.rst-content .seealso p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.wy-alert p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width:768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px;color:#fff;border:1px solid rgba(0,0,0,.1);background-color:#27ae60;text-decoration:none;font-weight:400;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 rgba(0,0,0,.1);outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:inset 0 -1px 0 0 rgba(0,0,0,.05),inset 0 2px 0 0 rgba(0,0,0,.1);padding:8px 12px 6px}.btn:visited{color:#fff}.btn-disabled,.btn-disabled:active,.btn-disabled:focus,.btn-disabled:hover,.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9!important}.btn-info:hover{background-color:#2e8ece!important}.btn-neutral{background-color:#f3f6f6!important;color:#404040!important}.btn-neutral:hover{background-color:#e5ebeb!important;color:#404040}.btn-neutral:visited{color:#404040!important}.btn-success{background-color:#27ae60!important}.btn-success:hover{background-color:#295!important}.btn-danger{background-color:#e74c3c!important}.btn-danger:hover{background-color:#ea6153!important}.btn-warning{background-color:#e67e22!important}.btn-warning:hover{background-color:#e98b39!important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f!important}.btn-link{background-color:transparent!important;color:#2980b9;box-shadow:none;border-color:transparent!important}.btn-link:active,.btn-link:hover{background-color:transparent!important;color:#409ad5!important;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:after,.wy-btn-group:before{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:1px solid #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:1px solid #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type=search]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned .wy-help-inline,.wy-form-aligned input,.wy-form-aligned label,.wy-form-aligned select,.wy-form-aligned textarea{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{margin:0}fieldset,legend{border:0;padding:0}legend{width:100%;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label,legend{display:block}label{margin:0 0 .3125em;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;max-width:1200px;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:after,.wy-control-group:before{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full input[type=color],.wy-control-group .wy-form-full input[type=date],.wy-control-group .wy-form-full input[type=datetime-local],.wy-control-group .wy-form-full input[type=datetime],.wy-control-group .wy-form-full input[type=email],.wy-control-group .wy-form-full input[type=month],.wy-control-group .wy-form-full input[type=number],.wy-control-group .wy-form-full input[type=password],.wy-control-group .wy-form-full input[type=search],.wy-control-group .wy-form-full input[type=tel],.wy-control-group .wy-form-full input[type=text],.wy-control-group .wy-form-full input[type=time],.wy-control-group .wy-form-full input[type=url],.wy-control-group .wy-form-full input[type=week],.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves input[type=color],.wy-control-group .wy-form-halves input[type=date],.wy-control-group .wy-form-halves input[type=datetime-local],.wy-control-group .wy-form-halves input[type=datetime],.wy-control-group .wy-form-halves input[type=email],.wy-control-group .wy-form-halves input[type=month],.wy-control-group .wy-form-halves input[type=number],.wy-control-group .wy-form-halves input[type=password],.wy-control-group .wy-form-halves input[type=search],.wy-control-group .wy-form-halves input[type=tel],.wy-control-group .wy-form-halves input[type=text],.wy-control-group .wy-form-halves input[type=time],.wy-control-group .wy-form-halves input[type=url],.wy-control-group .wy-form-halves input[type=week],.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds input[type=color],.wy-control-group .wy-form-thirds input[type=date],.wy-control-group .wy-form-thirds input[type=datetime-local],.wy-control-group .wy-form-thirds input[type=datetime],.wy-control-group .wy-form-thirds input[type=email],.wy-control-group .wy-form-thirds input[type=month],.wy-control-group .wy-form-thirds input[type=number],.wy-control-group .wy-form-thirds input[type=password],.wy-control-group .wy-form-thirds input[type=search],.wy-control-group .wy-form-thirds input[type=tel],.wy-control-group .wy-form-thirds input[type=text],.wy-control-group .wy-form-thirds input[type=time],.wy-control-group .wy-form-thirds input[type=url],.wy-control-group .wy-form-thirds input[type=week],.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full{float:left;display:block;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child,.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(odd){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child,.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control,.wy-control-no-input{margin:6px 0 0;font-size:90%}.wy-control-no-input{display:inline-block}.wy-control-group.fluid-input input[type=color],.wy-control-group.fluid-input input[type=date],.wy-control-group.fluid-input input[type=datetime-local],.wy-control-group.fluid-input input[type=datetime],.wy-control-group.fluid-input input[type=email],.wy-control-group.fluid-input input[type=month],.wy-control-group.fluid-input input[type=number],.wy-control-group.fluid-input input[type=password],.wy-control-group.fluid-input input[type=search],.wy-control-group.fluid-input input[type=tel],.wy-control-group.fluid-input input[type=text],.wy-control-group.fluid-input input[type=time],.wy-control-group.fluid-input input[type=url],.wy-control-group.fluid-input input[type=week]{width:100%}.wy-form-message-inline{padding-left:.3em;color:#666;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;*overflow:visible}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type=datetime-local]{padding:.34375em .625em}input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type=checkbox],input[type=radio],input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus{outline:0;outline:thin dotted\9;border-color:#333}input.no-focus:focus{border-color:#ccc!important}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type=color][disabled],input[type=date][disabled],input[type=datetime-local][disabled],input[type=datetime][disabled],input[type=email][disabled],input[type=month][disabled],input[type=number][disabled],input[type=password][disabled],input[type=search][disabled],input[type=tel][disabled],input[type=text][disabled],input[type=time][disabled],input[type=url][disabled],input[type=week][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,select:focus:invalid,textarea:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,select:focus:invalid:focus,textarea:focus:invalid:focus{border-color:#e74c3c}input[type=checkbox]:focus:invalid:focus,input[type=file]:focus:invalid:focus,input[type=radio]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}input[readonly],select[disabled],select[readonly],textarea[disabled],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:1px solid #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{left:0;top:0;width:36px;height:12px;background:#ccc}.wy-switch:after,.wy-switch:before{position:absolute;content:"";display:block;border-radius:4px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{width:18px;height:18px;background:#999;left:-3px;top:-3px}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27ae60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type=color],.wy-control-group.wy-control-group-error input[type=date],.wy-control-group.wy-control-group-error input[type=datetime-local],.wy-control-group.wy-control-group-error input[type=datetime],.wy-control-group.wy-control-group-error input[type=email],.wy-control-group.wy-control-group-error input[type=month],.wy-control-group.wy-control-group-error input[type=number],.wy-control-group.wy-control-group-error input[type=password],.wy-control-group.wy-control-group-error input[type=search],.wy-control-group.wy-control-group-error input[type=tel],.wy-control-group.wy-control-group-error input[type=text],.wy-control-group.wy-control-group-error input[type=time],.wy-control-group.wy-control-group-error input[type=url],.wy-control-group.wy-control-group-error input[type=week],.wy-control-group.wy-control-group-error textarea{border:1px solid #e74c3c}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width:480px){.wy-form button[type=submit]{margin:.7em 0 0}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=text],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week],.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0}.wy-form-message,.wy-form-message-inline,.wy-form .wy-help-inline{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width:768px){.tablet-hide{display:none}}@media screen and (max-width:480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.rst-content table.docutils,.rst-content table.field-list,.wy-table{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption,.wy-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list td,.rst-content table.field-list th,.wy-table td,.wy-table th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.rst-content table.docutils td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list td:first-child,.rst-content table.field-list th:first-child,.wy-table td:first-child,.wy-table th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead,.wy-table thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th,.wy-table thead th{font-weight:700;border-bottom:2px solid #e1e4e5}.rst-content table.docutils td,.rst-content table.field-list td,.wy-table td{background-color:transparent;vertical-align:middle}.rst-content table.docutils td p,.rst-content table.field-list td p,.wy-table td p{line-height:18px}.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child,.wy-table td p:last-child{margin-bottom:0}.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min,.wy-table .wy-table-cell-min{width:1%;padding-right:0}.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:grey;font-size:90%}.wy-table-tertiary{color:grey;font-size:80%}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,.wy-table-backed,.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td{background-color:#f3f6f6}.rst-content table.docutils,.wy-table-bordered-all{border:1px solid #e1e4e5}.rst-content table.docutils td,.wy-table-bordered-all td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.rst-content table.docutils tbody>tr:last-child td,.wy-table-bordered-all tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0!important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980b9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9b59b6}html{height:100%}body,html{overflow-x:hidden}body{font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-weight:400;color:#404040;min-height:100%;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22!important}a.wy-text-warning:hover{color:#eb9950!important}.wy-text-info{color:#2980b9!important}a.wy-text-info:hover{color:#409ad5!important}.wy-text-success{color:#27ae60!important}a.wy-text-success:hover{color:#36d278!important}.wy-text-danger{color:#e74c3c!important}a.wy-text-danger:hover{color:#ed7669!important}.wy-text-neutral{color:#404040!important}a.wy-text-neutral:hover{color:#595959!important}.rst-content .toctree-wrapper>p.caption,h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif}p{line-height:24px;font-size:16px;margin:0 0 24px}h1{font-size:175%}.rst-content .toctree-wrapper>p.caption,h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}.rst-content code,.rst-content tt,code{white-space:nowrap;max-width:100%;background:#fff;border:1px solid #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#e74c3c;overflow-x:auto}.rst-content tt.code-large,code.code-large{font-size:90%}.rst-content .section ul,.rst-content .toctree-wrapper ul,.rst-content section ul,.wy-plain-list-disc,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.rst-content .section ul li,.rst-content .toctree-wrapper ul li,.rst-content section ul li,.wy-plain-list-disc li,article ul li{list-style:disc;margin-left:24px}.rst-content .section ul li p:last-child,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li p:last-child,.rst-content .toctree-wrapper ul li ul,.rst-content section ul li p:last-child,.rst-content section ul li ul,.wy-plain-list-disc li p:last-child,.wy-plain-list-disc li ul,article ul li p:last-child,article ul li ul{margin-bottom:0}.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,.rst-content section ul li li,.wy-plain-list-disc li li,article ul li li{list-style:circle}.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,.rst-content section ul li li li,.wy-plain-list-disc li li li,article ul li li li{list-style:square}.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,.rst-content section ul li ol li,.wy-plain-list-disc li ol li,article ul li ol li{list-style:decimal}.rst-content .section ol,.rst-content .section ol.arabic,.rst-content .toctree-wrapper ol,.rst-content .toctree-wrapper ol.arabic,.rst-content section ol,.rst-content section ol.arabic,.wy-plain-list-decimal,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.rst-content .section ol.arabic li,.rst-content .section ol li,.rst-content .toctree-wrapper ol.arabic li,.rst-content .toctree-wrapper ol li,.rst-content section ol.arabic li,.rst-content section ol li,.wy-plain-list-decimal li,article ol li{list-style:decimal;margin-left:24px}.rst-content .section ol.arabic li ul,.rst-content .section ol li p:last-child,.rst-content .section ol li ul,.rst-content .toctree-wrapper ol.arabic li ul,.rst-content .toctree-wrapper ol li p:last-child,.rst-content .toctree-wrapper ol li ul,.rst-content section ol.arabic li ul,.rst-content section ol li p:last-child,.rst-content section ol li ul,.wy-plain-list-decimal li p:last-child,.wy-plain-list-decimal li ul,article ol li p:last-child,article ol li ul{margin-bottom:0}.rst-content .section ol.arabic li ul li,.rst-content .section ol li ul li,.rst-content .toctree-wrapper ol.arabic li ul li,.rst-content .toctree-wrapper ol li ul li,.rst-content section ol.arabic li ul li,.rst-content section ol li ul li,.wy-plain-list-decimal li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:after,.wy-breadcrumbs:before{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs>li{display:inline-block;padding-top:5px}.wy-breadcrumbs>li.wy-breadcrumbs-aside{float:right}.rst-content .wy-breadcrumbs>li code,.rst-content .wy-breadcrumbs>li tt,.wy-breadcrumbs>li .rst-content tt,.wy-breadcrumbs>li code{all:inherit;color:inherit}.breadcrumb-item:before{content:"/";color:#bbb;font-size:13px;padding:0 6px 0 3px}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width:480px){.wy-breadcrumbs-extra,.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:after,.wy-menu-horiz:before{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz li,.wy-menu-horiz ul{display:inline-block}.wy-menu-horiz li:hover{background:hsla(0,0%,100%,.1)}.wy-menu-horiz li.divide-left{border-left:1px solid #404040}.wy-menu-horiz li.divide-right{border-right:1px solid #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#55a5d9;height:32px;line-height:32px;padding:0 1.618em;margin:12px 0 0;display:block;font-weight:700;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:1px solid #404040}.wy-menu-vertical li.divide-bottom{border-bottom:1px solid #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:grey;border-right:1px solid #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.rst-content .wy-menu-vertical li tt,.wy-menu-vertical li .rst-content tt,.wy-menu-vertical li code{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li button.toctree-expand{display:block;float:left;margin-left:-1.2em;line-height:18px;color:#4d4d4d;border:none;background:none;padding:0}.wy-menu-vertical li.current>a,.wy-menu-vertical li.on a{color:#404040;font-weight:700;position:relative;background:#fcfcfc;border:none;padding:.4045em 1.618em}.wy-menu-vertical li.current>a:hover,.wy-menu-vertical li.on a:hover{background:#fcfcfc}.wy-menu-vertical li.current>a:hover button.toctree-expand,.wy-menu-vertical li.on a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand{display:block;line-height:18px;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:1px solid #c9c9c9;border-top:1px solid #c9c9c9}.wy-menu-vertical .toctree-l1.current .toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .toctree-l11>ul{display:none}.wy-menu-vertical .toctree-l1.current .current.toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .current.toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .current.toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .current.toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .current.toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .current.toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .current.toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .current.toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .current.toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .current.toctree-l11>ul{display:block}.wy-menu-vertical li.toctree-l3,.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a,.wy-menu-vertical li.toctree-l5 a,.wy-menu-vertical li.toctree-l6 a,.wy-menu-vertical li.toctree-l7 a,.wy-menu-vertical li.toctree-l8 a,.wy-menu-vertical li.toctree-l9 a,.wy-menu-vertical li.toctree-l10 a{color:#404040}.wy-menu-vertical li.toctree-l2 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l3 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l4 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l5 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l6 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l7 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l8 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l9 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l10 a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a,.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a,.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a,.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a,.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{display:block}.wy-menu-vertical li.toctree-l2.current>a{padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{padding:.4045em 1.618em .4045em 4.045em}.wy-menu-vertical li.toctree-l3.current>a{padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{padding:.4045em 1.618em .4045em 5.663em}.wy-menu-vertical li.toctree-l4.current>a{padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a{padding:.4045em 1.618em .4045em 7.281em}.wy-menu-vertical li.toctree-l5.current>a{padding:.4045em 7.281em}.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a{padding:.4045em 1.618em .4045em 8.899em}.wy-menu-vertical li.toctree-l6.current>a{padding:.4045em 8.899em}.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a{padding:.4045em 1.618em .4045em 10.517em}.wy-menu-vertical li.toctree-l7.current>a{padding:.4045em 10.517em}.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a{padding:.4045em 1.618em .4045em 12.135em}.wy-menu-vertical li.toctree-l8.current>a{padding:.4045em 12.135em}.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a{padding:.4045em 1.618em .4045em 13.753em}.wy-menu-vertical li.toctree-l9.current>a{padding:.4045em 13.753em}.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a{padding:.4045em 1.618em .4045em 15.371em}.wy-menu-vertical li.toctree-l10.current>a{padding:.4045em 15.371em}.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{padding:.4045em 1.618em .4045em 16.989em}.wy-menu-vertical li.toctree-l2.current>a,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{background:#c9c9c9}.wy-menu-vertical li.toctree-l2 button.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3.current>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{background:#bdbdbd}.wy-menu-vertical li.toctree-l3 button.toctree-expand{color:#969696}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:400}.wy-menu-vertical a{line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover button.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-menu-vertical a:active button.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980b9;text-align:center;color:#fcfcfc}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a{color:#fcfcfc;font-size:100%;font-weight:700;display:inline-block;padding:4px 6px;margin-bottom:.809em;max-width:100%}.wy-side-nav-search .wy-dropdown>a:hover,.wy-side-nav-search .wy-dropdown>aactive,.wy-side-nav-search .wy-dropdown>afocus,.wy-side-nav-search>a:hover,.wy-side-nav-search>aactive,.wy-side-nav-search>afocus{background:hsla(0,0%,100%,.1)}.wy-side-nav-search .wy-dropdown>a img.logo,.wy-side-nav-search>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search .wy-dropdown>a.icon,.wy-side-nav-search>a.icon{display:block}.wy-side-nav-search .wy-dropdown>a.icon img.logo,.wy-side-nav-search>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.switch-menus{position:relative;display:block;margin-top:-.4045em;margin-bottom:.809em;font-weight:400;color:hsla(0,0%,100%,.3)}.wy-side-nav-search>div.switch-menus>div.language-switch,.wy-side-nav-search>div.switch-menus>div.version-switch{display:inline-block;padding:.2em}.wy-side-nav-search>div.switch-menus>div.language-switch select,.wy-side-nav-search>div.switch-menus>div.version-switch select{display:inline-block;margin-right:-2rem;padding-right:2rem;max-width:240px;text-align-last:center;background:none;border:none;border-radius:0;box-shadow:none;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-size:1em;font-weight:400;color:hsla(0,0%,100%,.3);cursor:pointer;appearance:none;-webkit-appearance:none;-moz-appearance:none}.wy-side-nav-search>div.switch-menus>div.language-switch select:active,.wy-side-nav-search>div.switch-menus>div.language-switch select:focus,.wy-side-nav-search>div.switch-menus>div.language-switch select:hover,.wy-side-nav-search>div.switch-menus>div.version-switch select:active,.wy-side-nav-search>div.switch-menus>div.version-switch select:focus,.wy-side-nav-search>div.switch-menus>div.version-switch select:hover{background:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.5)}.wy-side-nav-search>div.switch-menus>div.language-switch select option,.wy-side-nav-search>div.switch-menus>div.version-switch select option{color:#000}.wy-side-nav-search>div.switch-menus>div.language-switch:has(>select):after,.wy-side-nav-search>div.switch-menus>div.version-switch:has(>select):after{display:inline-block;width:1.5em;height:100%;padding:.1em;content:"\f0d7";font-size:1em;line-height:1.2em;font-family:FontAwesome;text-align:center;pointer-events:none;box-sizing:border-box}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:after,.wy-nav-top:before{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:700}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:grey}footer p{margin-bottom:12px}.rst-content footer span.commit tt,footer span.commit .rst-content tt,footer span.commit code{padding:0;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:1em;background:none;border:none;color:grey}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:after,.rst-footer-buttons:before{width:100%;display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:after,.rst-breadcrumbs-buttons:before{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:1px solid #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:1px solid #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:grey;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width:768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-menu.wy-menu-vertical,.wy-side-nav-search,.wy-side-scroll{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width:1100px){.wy-nav-content-wrap{background:rgba(0,0,0,.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,.wy-nav-side,footer{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:after,.rst-versions .rst-current-version:before{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-content .eqno .rst-versions .rst-current-version .headerlink,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-content p .rst-versions .rst-current-version .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .icon,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-versions .rst-current-version .rst-content .eqno .headerlink,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-versions .rst-current-version .rst-content p .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-versions .rst-current-version .wy-menu-vertical li button.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version button.toctree-expand{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions .rst-other-versions .rtd-current-item{font-weight:700}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}#flyout-search-form{padding:6px}.rst-content .toctree-wrapper>p.caption,.rst-content h1,.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6{margin-bottom:24px}.rst-content img{max-width:100%;height:auto}.rst-content div.figure,.rst-content figure{margin-bottom:24px}.rst-content div.figure .caption-text,.rst-content figure .caption-text{font-style:italic}.rst-content div.figure p:last-child.caption,.rst-content figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center,.rst-content figure.align-center{text-align:center}.rst-content .section>a>img,.rst-content .section>img,.rst-content section>a>img,.rst-content section>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"\f08e";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;display:block;overflow:auto}.rst-content div[class^=highlight],.rst-content pre.literal-block{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px}.rst-content div[class^=highlight] div[class^=highlight],.rst-content pre.literal-block div[class^=highlight]{padding:0;border:none;margin:0}.rst-content div[class^=highlight] td.code{width:100%}.rst-content .linenodiv pre{border-right:1px solid #e6e9ea;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^=highlight] pre{white-space:pre;margin:0;padding:12px;display:block;overflow:auto}.rst-content div[class^=highlight] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content .linenodiv pre,.rst-content div[class^=highlight] pre,.rst-content pre.literal-block{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:12px;line-height:1.4}.rst-content div.highlight .gp,.rst-content div.highlight span.linenos{user-select:none;pointer-events:none}.rst-content div.highlight span.linenos{display:inline-block;padding-left:0;padding-right:12px;margin-right:12px;border-right:1px solid #e6e9ea}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning{clear:both}.rst-content .admonition-todo .last,.rst-content .admonition-todo>:last-child,.rst-content .admonition .last,.rst-content .admonition>:last-child,.rst-content .attention .last,.rst-content .attention>:last-child,.rst-content .caution .last,.rst-content .caution>:last-child,.rst-content .danger .last,.rst-content .danger>:last-child,.rst-content .error .last,.rst-content .error>:last-child,.rst-content .hint .last,.rst-content .hint>:last-child,.rst-content .important .last,.rst-content .important>:last-child,.rst-content .note .last,.rst-content .note>:last-child,.rst-content .seealso .last,.rst-content .seealso>:last-child,.rst-content .tip .last,.rst-content .tip>:last-child,.rst-content .warning .last,.rst-content .warning>:last-child{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha>li,.rst-content .toctree-wrapper ol.loweralpha,.rst-content .toctree-wrapper ol.loweralpha>li,.rst-content section ol.loweralpha,.rst-content section ol.loweralpha>li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha>li,.rst-content .toctree-wrapper ol.upperalpha,.rst-content .toctree-wrapper ol.upperalpha>li,.rst-content section ol.upperalpha,.rst-content section ol.upperalpha>li{list-style:upper-alpha}.rst-content .section ol li>*,.rst-content .section ul li>*,.rst-content .toctree-wrapper ol li>*,.rst-content .toctree-wrapper ul li>*,.rst-content section ol li>*,.rst-content section ul li>*{margin-top:12px;margin-bottom:12px}.rst-content .section ol li>:first-child,.rst-content .section ul li>:first-child,.rst-content .toctree-wrapper ol li>:first-child,.rst-content .toctree-wrapper ul li>:first-child,.rst-content section ol li>:first-child,.rst-content section ul li>:first-child{margin-top:0}.rst-content .section ol li>p,.rst-content .section ol li>p:last-child,.rst-content .section ul li>p,.rst-content .section ul li>p:last-child,.rst-content .toctree-wrapper ol li>p,.rst-content .toctree-wrapper ol li>p:last-child,.rst-content .toctree-wrapper ul li>p,.rst-content .toctree-wrapper ul li>p:last-child,.rst-content section ol li>p,.rst-content section ol li>p:last-child,.rst-content section ul li>p,.rst-content section ul li>p:last-child{margin-bottom:12px}.rst-content .section ol li>p:only-child,.rst-content .section ol li>p:only-child:last-child,.rst-content .section ul li>p:only-child,.rst-content .section ul li>p:only-child:last-child,.rst-content .toctree-wrapper ol li>p:only-child,.rst-content .toctree-wrapper ol li>p:only-child:last-child,.rst-content .toctree-wrapper ul li>p:only-child,.rst-content .toctree-wrapper ul li>p:only-child:last-child,.rst-content section ol li>p:only-child,.rst-content section ol li>p:only-child:last-child,.rst-content section ul li>p:only-child,.rst-content section ul li>p:only-child:last-child{margin-bottom:0}.rst-content .section ol li>ol,.rst-content .section ol li>ul,.rst-content .section ul li>ol,.rst-content .section ul li>ul,.rst-content .toctree-wrapper ol li>ol,.rst-content .toctree-wrapper ol li>ul,.rst-content .toctree-wrapper ul li>ol,.rst-content .toctree-wrapper ul li>ul,.rst-content section ol li>ol,.rst-content section ol li>ul,.rst-content section ul li>ol,.rst-content section ul li>ul{margin-bottom:12px}.rst-content .section ol.simple li>*,.rst-content .section ol.simple li ol,.rst-content .section ol.simple li ul,.rst-content .section ul.simple li>*,.rst-content .section ul.simple li ol,.rst-content .section ul.simple li ul,.rst-content .toctree-wrapper ol.simple li>*,.rst-content .toctree-wrapper ol.simple li ol,.rst-content .toctree-wrapper ol.simple li ul,.rst-content .toctree-wrapper ul.simple li>*,.rst-content .toctree-wrapper ul.simple li ol,.rst-content .toctree-wrapper ul.simple li ul,.rst-content section ol.simple li>*,.rst-content section ol.simple li ol,.rst-content section ol.simple li ul,.rst-content section ul.simple li>*,.rst-content section ul.simple li ol,.rst-content section ul.simple li ul{margin-top:0;margin-bottom:0}.rst-content .line-block{margin-left:0;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0 0 24px 24px}.rst-content .align-left{float:left;margin:0 24px 24px 0}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink{opacity:0;font-size:14px;font-family:FontAwesome;margin-left:.5em}.rst-content .code-block-caption .headerlink:focus,.rst-content .code-block-caption:hover .headerlink,.rst-content .eqno .headerlink:focus,.rst-content .eqno:hover .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink:focus,.rst-content .toctree-wrapper>p.caption:hover .headerlink,.rst-content dl dt .headerlink:focus,.rst-content dl dt:hover .headerlink,.rst-content h1 .headerlink:focus,.rst-content h1:hover .headerlink,.rst-content h2 .headerlink:focus,.rst-content h2:hover .headerlink,.rst-content h3 .headerlink:focus,.rst-content h3:hover .headerlink,.rst-content h4 .headerlink:focus,.rst-content h4:hover .headerlink,.rst-content h5 .headerlink:focus,.rst-content h5:hover .headerlink,.rst-content h6 .headerlink:focus,.rst-content h6:hover .headerlink,.rst-content p.caption .headerlink:focus,.rst-content p.caption:hover .headerlink,.rst-content p .headerlink:focus,.rst-content p:hover .headerlink,.rst-content table>caption .headerlink:focus,.rst-content table>caption:hover .headerlink{opacity:1}.rst-content p a{overflow-wrap:anywhere}.rst-content .wy-table td p,.rst-content .wy-table td ul,.rst-content .wy-table th p,.rst-content .wy-table th ul,.rst-content table.docutils td p,.rst-content table.docutils td ul,.rst-content table.docutils th p,.rst-content table.docutils th ul,.rst-content table.field-list td p,.rst-content table.field-list td ul,.rst-content table.field-list th p,.rst-content table.field-list th ul{font-size:inherit}.rst-content .btn:focus{outline:2px solid}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:1px solid #e1e4e5}.rst-content .sidebar dl,.rst-content .sidebar p,.rst-content .sidebar ul{font-size:90%}.rst-content .sidebar .last,.rst-content .sidebar>:last-child{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif;font-weight:700;background:#e1e4e5;padding:6px 12px;margin:-24px -24px 24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;box-shadow:0 0 0 2px #f1c40f;display:inline;font-weight:700}.rst-content .citation-reference,.rst-content .footnote-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content .citation-reference>span.fn-bracket,.rst-content .footnote-reference>span.fn-bracket{display:none}.rst-content .hlist{width:100%}.rst-content dl dt span.classifier:before{content:" : "}.rst-content dl dt span.classifier-delimiter{display:none!important}html.writer-html4 .rst-content table.docutils.citation,html.writer-html4 .rst-content table.docutils.footnote{background:none;border:none}html.writer-html4 .rst-content table.docutils.citation td,html.writer-html4 .rst-content table.docutils.citation tr,html.writer-html4 .rst-content table.docutils.footnote td,html.writer-html4 .rst-content table.docutils.footnote tr{border:none;background-color:transparent!important;white-space:normal}html.writer-html4 .rst-content table.docutils.citation td.label,html.writer-html4 .rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{display:grid;grid-template-columns:auto minmax(80%,95%)}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{display:inline-grid;grid-template-columns:max-content auto}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{display:grid;grid-template-columns:auto auto minmax(.65rem,auto) minmax(40%,95%)}html.writer-html5 .rst-content aside.citation>span.label,html.writer-html5 .rst-content aside.footnote>span.label,html.writer-html5 .rst-content div.citation>span.label{grid-column-start:1;grid-column-end:2}html.writer-html5 .rst-content aside.citation>span.backrefs,html.writer-html5 .rst-content aside.footnote>span.backrefs,html.writer-html5 .rst-content div.citation>span.backrefs{grid-column-start:2;grid-column-end:3;grid-row-start:1;grid-row-end:3}html.writer-html5 .rst-content aside.citation>p,html.writer-html5 .rst-content aside.footnote>p,html.writer-html5 .rst-content div.citation>p{grid-column-start:4;grid-column-end:5}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{margin-bottom:24px}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{padding-left:1rem}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dd,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dd,html.writer-html5 .rst-content dl.footnote>dt{margin-bottom:0}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{font-size:.9rem}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.footnote>dt{margin:0 .5rem .5rem 0;line-height:1.2rem;word-break:break-all;font-weight:400}html.writer-html5 .rst-content dl.citation>dt>span.brackets:before,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:before{content:"["}html.writer-html5 .rst-content dl.citation>dt>span.brackets:after,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:after{content:"]"}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a{word-break:keep-all}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a:not(:first-child):before,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.footnote>dd{margin:0 0 .5rem;line-height:1.2rem}html.writer-html5 .rst-content dl.citation>dd p,html.writer-html5 .rst-content dl.footnote>dd p{font-size:.9rem}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{padding-left:1rem;padding-right:1rem;font-size:.9rem;line-height:1.2rem}html.writer-html5 .rst-content aside.citation p,html.writer-html5 .rst-content aside.footnote p,html.writer-html5 .rst-content div.citation p{font-size:.9rem;line-height:1.2rem;margin-bottom:12px}html.writer-html5 .rst-content aside.citation span.backrefs,html.writer-html5 .rst-content aside.footnote span.backrefs,html.writer-html5 .rst-content div.citation span.backrefs{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content aside.citation span.backrefs>a,html.writer-html5 .rst-content aside.footnote span.backrefs>a,html.writer-html5 .rst-content div.citation span.backrefs>a{word-break:keep-all}html.writer-html5 .rst-content aside.citation span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content aside.footnote span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content div.citation span.backrefs>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content aside.citation span.label,html.writer-html5 .rst-content aside.footnote span.label,html.writer-html5 .rst-content div.citation span.label{line-height:1.2rem}html.writer-html5 .rst-content aside.citation-list,html.writer-html5 .rst-content aside.footnote-list,html.writer-html5 .rst-content div.citation-list{margin-bottom:24px}html.writer-html5 .rst-content dl.option-list kbd{font-size:.9rem}.rst-content table.docutils.footnote,html.writer-html4 .rst-content table.docutils.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content aside.footnote-list aside.footnote,html.writer-html5 .rst-content div.citation-list>div.citation,html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{color:grey}.rst-content table.docutils.footnote code,.rst-content table.docutils.footnote tt,html.writer-html4 .rst-content table.docutils.citation code,html.writer-html4 .rst-content table.docutils.citation tt,html.writer-html5 .rst-content aside.footnote-list aside.footnote code,html.writer-html5 .rst-content aside.footnote-list aside.footnote tt,html.writer-html5 .rst-content aside.footnote code,html.writer-html5 .rst-content aside.footnote tt,html.writer-html5 .rst-content div.citation-list>div.citation code,html.writer-html5 .rst-content div.citation-list>div.citation tt,html.writer-html5 .rst-content dl.citation code,html.writer-html5 .rst-content dl.citation tt,html.writer-html5 .rst-content dl.footnote code,html.writer-html5 .rst-content dl.footnote tt{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}html.writer-html5 .rst-content table.docutils th{border:1px solid #e1e4e5}html.writer-html5 .rst-content table.docutils td>p,html.writer-html5 .rst-content table.docutils th>p{line-height:1rem;margin-bottom:0;font-size:.9rem}.rst-content table.docutils td .last,.rst-content table.docutils td .last>:last-child{margin-bottom:0}.rst-content table.field-list,.rst-content table.field-list td{border:none}.rst-content table.field-list td p{line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content code,.rst-content tt{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;padding:2px 5px}.rst-content code big,.rst-content code em,.rst-content tt big,.rst-content tt em{font-size:100%!important;line-height:normal}.rst-content code.literal,.rst-content tt.literal{color:#e74c3c;white-space:normal}.rst-content code.xref,.rst-content tt.xref,a .rst-content code,a .rst-content tt{font-weight:700;color:#404040;overflow-wrap:normal}.rst-content kbd,.rst-content pre,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace}.rst-content a code,.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px}.rst-content dl ol,.rst-content dl p,.rst-content dl table,.rst-content dl ul{margin-bottom:12px}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl dd>ol:last-child,.rst-content dl dd>p:last-child,.rst-content dl dd>table:last-child,.rst-content dl dd>ul:last-child{margin-bottom:0}html.writer-html4 .rst-content dl:not(.docutils),html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple){margin-bottom:24px}html.writer-html4 .rst-content dl:not(.docutils)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:3px solid #6ab0de;padding:6px;position:relative}html.writer-html4 .rst-content dl:not(.docutils)>dt:before,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:before{color:#6ab0de}html.writer-html4 .rst-content dl:not(.docutils)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{margin-bottom:6px;border:none;border-left:3px solid #ccc;background:#f0f0f0;color:#555}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils)>dt:first-child,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:first-child{margin-top:0}html.writer-html4 .rst-content dl:not(.docutils) code.descclassname,html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descclassname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{background-color:transparent;border:none;padding:0;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .optional,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .property,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .property{display:inline-block;padding-right:8px;max-width:100%}html.writer-html4 .rst-content dl:not(.docutils) .k,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .k{font-style:italic}html.writer-html4 .rst-content dl:not(.docutils) .descclassname,html.writer-html4 .rst-content dl:not(.docutils) .descname,html.writer-html4 .rst-content dl:not(.docutils) .sig-name,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .sig-name{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#000}.rst-content .viewcode-back,.rst-content .viewcode-link{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content code.download,.rst-content tt.download{background:inherit;padding:inherit;font-weight:400;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content code.download span:first-child,.rst-content tt.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{margin-right:4px}.rst-content .guilabel,.rst-content .menuselection{font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content .guilabel,.rst-content .menuselection{border:1px solid #7fbbe3;background:#e7f2fa}.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>.kbd,.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>kbd{color:inherit;font-size:80%;background-color:#fff;border:1px solid #a6a6a6;border-radius:4px;box-shadow:0 2px grey;padding:2.4px 6px;margin:auto 0}.rst-content .versionmodified{font-style:italic}@media screen and (max-width:480px){.rst-content .sidebar{width:100%;float:none;margin-left:0}}span[id*=MathJax-Span]{color:#404040}.math{text-align:center}@font-face{font-family:Lato;src:url(fonts/lato-normal.woff2?bd03a2cc277bbbc338d464e679fe9942) format("woff2"),url(fonts/lato-normal.woff?27bd77b9162d388cb8d4c4217c7c5e2a) format("woff");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold.woff2?cccb897485813c7c256901dbca54ecf2) format("woff2"),url(fonts/lato-bold.woff?d878b6c29b10beca227e9eef4246111b) format("woff");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold-italic.woff2?0b6bb6725576b072c5d0b02ecdd1900d) format("woff2"),url(fonts/lato-bold-italic.woff?9c7e4e9eb485b4a121c760e61bc3707c) format("woff");font-weight:700;font-style:italic;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-normal-italic.woff2?4eb103b4d12be57cb1d040ed5e162e9d) format("woff2"),url(fonts/lato-normal-italic.woff?f28f2d6482446544ef1ea1ccc6dd5892) format("woff");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:400;src:url(fonts/Roboto-Slab-Regular.woff2?7abf5b8d04d26a2cafea937019bca958) format("woff2"),url(fonts/Roboto-Slab-Regular.woff?c1be9284088d487c5e3ff0a10a92e58c) format("woff");font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:700;src:url(fonts/Roboto-Slab-Bold.woff2?9984f4a9bda09be08e83f2506954adbe) format("woff2"),url(fonts/Roboto-Slab-Bold.woff?bed5564a116b05148e3b3bea6fb1162a) format("woff");font-display:block}
\ No newline at end of file
diff --git a/_build/html/_static/doctools.js b/_build/html/_static/doctools.js
new file mode 100644
index 00000000..d06a71d7
--- /dev/null
+++ b/_build/html/_static/doctools.js
@@ -0,0 +1,156 @@
+/*
+ * doctools.js
+ * ~~~~~~~~~~~
+ *
+ * Base JavaScript utilities for all Sphinx HTML documentation.
+ *
+ * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+"use strict";
+
+const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([
+ "TEXTAREA",
+ "INPUT",
+ "SELECT",
+ "BUTTON",
+]);
+
+const _ready = (callback) => {
+ if (document.readyState !== "loading") {
+ callback();
+ } else {
+ document.addEventListener("DOMContentLoaded", callback);
+ }
+};
+
+/**
+ * Small JavaScript module for the documentation.
+ */
+const Documentation = {
+ init: () => {
+ Documentation.initDomainIndexTable();
+ Documentation.initOnKeyListeners();
+ },
+
+ /**
+ * i18n support
+ */
+ TRANSLATIONS: {},
+ PLURAL_EXPR: (n) => (n === 1 ? 0 : 1),
+ LOCALE: "unknown",
+
+ // gettext and ngettext don't access this so that the functions
+ // can safely bound to a different name (_ = Documentation.gettext)
+ gettext: (string) => {
+ const translated = Documentation.TRANSLATIONS[string];
+ switch (typeof translated) {
+ case "undefined":
+ return string; // no translation
+ case "string":
+ return translated; // translation exists
+ default:
+ return translated[0]; // (singular, plural) translation tuple exists
+ }
+ },
+
+ ngettext: (singular, plural, n) => {
+ const translated = Documentation.TRANSLATIONS[singular];
+ if (typeof translated !== "undefined")
+ return translated[Documentation.PLURAL_EXPR(n)];
+ return n === 1 ? singular : plural;
+ },
+
+ addTranslations: (catalog) => {
+ Object.assign(Documentation.TRANSLATIONS, catalog.messages);
+ Documentation.PLURAL_EXPR = new Function(
+ "n",
+ `return (${catalog.plural_expr})`
+ );
+ Documentation.LOCALE = catalog.locale;
+ },
+
+ /**
+ * helper function to focus on search bar
+ */
+ focusSearchBar: () => {
+ document.querySelectorAll("input[name=q]")[0]?.focus();
+ },
+
+ /**
+ * Initialise the domain index toggle buttons
+ */
+ initDomainIndexTable: () => {
+ const toggler = (el) => {
+ const idNumber = el.id.substr(7);
+ const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`);
+ if (el.src.substr(-9) === "minus.png") {
+ el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`;
+ toggledRows.forEach((el) => (el.style.display = "none"));
+ } else {
+ el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`;
+ toggledRows.forEach((el) => (el.style.display = ""));
+ }
+ };
+
+ const togglerElements = document.querySelectorAll("img.toggler");
+ togglerElements.forEach((el) =>
+ el.addEventListener("click", (event) => toggler(event.currentTarget))
+ );
+ togglerElements.forEach((el) => (el.style.display = ""));
+ if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler);
+ },
+
+ initOnKeyListeners: () => {
+ // only install a listener if it is really needed
+ if (
+ !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS &&
+ !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS
+ )
+ return;
+
+ document.addEventListener("keydown", (event) => {
+ // bail for input elements
+ if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return;
+ // bail with special keys
+ if (event.altKey || event.ctrlKey || event.metaKey) return;
+
+ if (!event.shiftKey) {
+ switch (event.key) {
+ case "ArrowLeft":
+ if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
+
+ const prevLink = document.querySelector('link[rel="prev"]');
+ if (prevLink && prevLink.href) {
+ window.location.href = prevLink.href;
+ event.preventDefault();
+ }
+ break;
+ case "ArrowRight":
+ if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
+
+ const nextLink = document.querySelector('link[rel="next"]');
+ if (nextLink && nextLink.href) {
+ window.location.href = nextLink.href;
+ event.preventDefault();
+ }
+ break;
+ }
+ }
+
+ // some keyboard layouts may need Shift to get /
+ switch (event.key) {
+ case "/":
+ if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break;
+ Documentation.focusSearchBar();
+ event.preventDefault();
+ }
+ });
+ },
+};
+
+// quick alias for translations
+const _ = Documentation.gettext;
+
+_ready(Documentation.init);
diff --git a/_build/html/_static/documentation_options.js b/_build/html/_static/documentation_options.js
new file mode 100644
index 00000000..b57ae3b8
--- /dev/null
+++ b/_build/html/_static/documentation_options.js
@@ -0,0 +1,14 @@
+var DOCUMENTATION_OPTIONS = {
+ URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
+ VERSION: '',
+ LANGUAGE: 'en',
+ COLLAPSE_INDEX: false,
+ BUILDER: 'html',
+ FILE_SUFFIX: '.html',
+ LINK_SUFFIX: '.html',
+ HAS_SOURCE: true,
+ SOURCELINK_SUFFIX: '.txt',
+ NAVIGATION_WITH_KEYS: false,
+ SHOW_SEARCH_SUMMARY: true,
+ ENABLE_SEARCH_SHORTCUTS: true,
+};
\ No newline at end of file
diff --git a/_build/html/_static/file.png b/_build/html/_static/file.png
new file mode 100644
index 00000000..a858a410
Binary files /dev/null and b/_build/html/_static/file.png differ
diff --git a/_build/html/_static/fonts/Lato/lato-bold.eot b/_build/html/_static/fonts/Lato/lato-bold.eot
new file mode 100644
index 00000000..3361183a
Binary files /dev/null and b/_build/html/_static/fonts/Lato/lato-bold.eot differ
diff --git a/_build/html/_static/fonts/Lato/lato-bold.ttf b/_build/html/_static/fonts/Lato/lato-bold.ttf
new file mode 100644
index 00000000..29f691d5
Binary files /dev/null and b/_build/html/_static/fonts/Lato/lato-bold.ttf differ
diff --git a/_build/html/_static/fonts/Lato/lato-bold.woff b/_build/html/_static/fonts/Lato/lato-bold.woff
new file mode 100644
index 00000000..c6dff51f
Binary files /dev/null and b/_build/html/_static/fonts/Lato/lato-bold.woff differ
diff --git a/_build/html/_static/fonts/Lato/lato-bold.woff2 b/_build/html/_static/fonts/Lato/lato-bold.woff2
new file mode 100644
index 00000000..bb195043
Binary files /dev/null and b/_build/html/_static/fonts/Lato/lato-bold.woff2 differ
diff --git a/_build/html/_static/fonts/Lato/lato-bolditalic.eot b/_build/html/_static/fonts/Lato/lato-bolditalic.eot
new file mode 100644
index 00000000..3d415493
Binary files /dev/null and b/_build/html/_static/fonts/Lato/lato-bolditalic.eot differ
diff --git a/_build/html/_static/fonts/Lato/lato-bolditalic.ttf b/_build/html/_static/fonts/Lato/lato-bolditalic.ttf
new file mode 100644
index 00000000..f402040b
Binary files /dev/null and b/_build/html/_static/fonts/Lato/lato-bolditalic.ttf differ
diff --git a/_build/html/_static/fonts/Lato/lato-bolditalic.woff b/_build/html/_static/fonts/Lato/lato-bolditalic.woff
new file mode 100644
index 00000000..88ad05b9
Binary files /dev/null and b/_build/html/_static/fonts/Lato/lato-bolditalic.woff differ
diff --git a/_build/html/_static/fonts/Lato/lato-bolditalic.woff2 b/_build/html/_static/fonts/Lato/lato-bolditalic.woff2
new file mode 100644
index 00000000..c4e3d804
Binary files /dev/null and b/_build/html/_static/fonts/Lato/lato-bolditalic.woff2 differ
diff --git a/_build/html/_static/fonts/Lato/lato-italic.eot b/_build/html/_static/fonts/Lato/lato-italic.eot
new file mode 100644
index 00000000..3f826421
Binary files /dev/null and b/_build/html/_static/fonts/Lato/lato-italic.eot differ
diff --git a/_build/html/_static/fonts/Lato/lato-italic.ttf b/_build/html/_static/fonts/Lato/lato-italic.ttf
new file mode 100644
index 00000000..b4bfc9b2
Binary files /dev/null and b/_build/html/_static/fonts/Lato/lato-italic.ttf differ
diff --git a/_build/html/_static/fonts/Lato/lato-italic.woff b/_build/html/_static/fonts/Lato/lato-italic.woff
new file mode 100644
index 00000000..76114bc0
Binary files /dev/null and b/_build/html/_static/fonts/Lato/lato-italic.woff differ
diff --git a/_build/html/_static/fonts/Lato/lato-italic.woff2 b/_build/html/_static/fonts/Lato/lato-italic.woff2
new file mode 100644
index 00000000..3404f37e
Binary files /dev/null and b/_build/html/_static/fonts/Lato/lato-italic.woff2 differ
diff --git a/_build/html/_static/fonts/Lato/lato-regular.eot b/_build/html/_static/fonts/Lato/lato-regular.eot
new file mode 100644
index 00000000..11e3f2a5
Binary files /dev/null and b/_build/html/_static/fonts/Lato/lato-regular.eot differ
diff --git a/_build/html/_static/fonts/Lato/lato-regular.ttf b/_build/html/_static/fonts/Lato/lato-regular.ttf
new file mode 100644
index 00000000..74decd9e
Binary files /dev/null and b/_build/html/_static/fonts/Lato/lato-regular.ttf differ
diff --git a/_build/html/_static/fonts/Lato/lato-regular.woff b/_build/html/_static/fonts/Lato/lato-regular.woff
new file mode 100644
index 00000000..ae1307ff
Binary files /dev/null and b/_build/html/_static/fonts/Lato/lato-regular.woff differ
diff --git a/_build/html/_static/fonts/Lato/lato-regular.woff2 b/_build/html/_static/fonts/Lato/lato-regular.woff2
new file mode 100644
index 00000000..3bf98433
Binary files /dev/null and b/_build/html/_static/fonts/Lato/lato-regular.woff2 differ
diff --git a/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot b/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot
new file mode 100644
index 00000000..79dc8efe
Binary files /dev/null and b/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot differ
diff --git a/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf b/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf
new file mode 100644
index 00000000..df5d1df2
Binary files /dev/null and b/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf differ
diff --git a/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff b/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff
new file mode 100644
index 00000000..6cb60000
Binary files /dev/null and b/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff differ
diff --git a/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 b/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2
new file mode 100644
index 00000000..7059e231
Binary files /dev/null and b/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 differ
diff --git a/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot b/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot
new file mode 100644
index 00000000..2f7ca78a
Binary files /dev/null and b/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot differ
diff --git a/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf b/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf
new file mode 100644
index 00000000..eb52a790
Binary files /dev/null and b/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf differ
diff --git a/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff b/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff
new file mode 100644
index 00000000..f815f63f
Binary files /dev/null and b/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff differ
diff --git a/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 b/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2
new file mode 100644
index 00000000..f2c76e5b
Binary files /dev/null and b/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 differ
diff --git a/_build/html/_static/jquery.js b/_build/html/_static/jquery.js
new file mode 100644
index 00000000..c4c6022f
--- /dev/null
+++ b/_build/html/_static/jquery.js
@@ -0,0 +1,2 @@
+/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */
+!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"
La configuración de LibreQoS para cada shaper box se almacena en el archivo /etc/lqos.conf.
+
Edite el archivo para que coincida con su configuración
+
sudonano/etc/lqos.conf
+
+
+
En la sección [bridge] , cambie to_internet y to_network para que coincida con sus interfaces de red.
+
+
to_internet="enp1s0f1"
+
to_network="enp1s0f2"
+
+
Luego, si usa Bifrost/XDP, configure use_xdp_bridge=true en la misma sección [bridge]. Si no está seguro de que lo necesite, le recomendamos dejarlo como false.
+
+
Configure downlink_bandwidth_mbps y uplink_bandwidth_mbps para que coincidan con el ancho de banda en Mbps de la conexión a internet de subida/WAN de su red. Puede hacer lo mismo con generated_pn_download_mbps y generated_pn_upload_mbps.
+
to_internet sería la interfaz que da a su enrutador de borde y a la red de Internet en generla
+
to_network sería la interfaz que da a su enrutador central (o red interna puenteada si su red está puenteada)
+
+
Nota: Si observa que el tráfico no se está modelando cuando debería, asegúrese de intercambiar el orden de las interfaces y reinicie lqosd, así como lqos_scheduler con sudosystemctlrestartlqosdlqos_scheduler.
+
Después de cambiar cualquier parte de /etc/lqos.conf, se recomienda encarecidamente reiniciar siempre lqosd, utilizando sudosystemctlrestartlqosd. Esto vuelve a analizar cualquier nuevo valor en lqos.conf, haciendo que esos nuevos valores sean accesibles tanto para el lado Rust como para el lado Python del código.
Network.json permite a los operadores de ISP definir una topología de red jerárquica o una topología de red plana.
+
Si planea utilizar las integraciones UISP, Splynx o Netzur integradas, no es necesario que cree un archivo network.json todavía.
+Si planea utilizar la integración UISP integrada, esta se creará automáticamente la primera vez que se ejecute (suponiendo que network.json aún no exista).
+
Si no va a utilizar una integración, puede definir manualmente el archivo network.json siguiendo el archivo de plantilla: network.example.json
+
+-----------------------------------------------------------------------+
+| Entire Network |
++-----------------------+-----------------------+-----------------------+
+| Parent Node A | Parent Node B | Parent Node C |
++-----------------------+-------+-------+-------+-----------------------+
+| Parent Node D | Sub 3 | Sub 4 | Sub 5 | Sub 6 | Sub 7 | Parent Node F |
++-------+-------+-------+-------+-------+-------+-------+-------+-------+
+| Sub 1 | Sub 2 | | | | Sub 8 | Sub 9 |
++-------+-------+-------+-----------------------+-------+-------+-------+
+
+
+
Para redes sin nodos principales (sin puntos de acceso o sitios estrictamente definidos), edite el archivo network.json para utilizar una topología de red plana con
+nanonetwork.json
+estableciendo el siguiente contenido del archivo:
para convertir manualNetwork.csv en un archivo network.json.
+manualNetwork.csv se puede copiar desde el archivo de plantilla, manualNetwork.template.csv.
+
Nota: El nombre del nodo principal debe coincidir con el utilizado para los clientes en ShapedDevices.csv.
LibreQoS configura los dispositivos individuales según sus direcciones IP, que se agrupan en «circuitos».
+
Un circuito representa el servicio de Internet de un suscriptor de ISP, que puede tener una sola IP asociada (por ejemplo, al enrutador del suscriptor se le puede asignar una sola IPv4 /32) o puede tener varias IP asociadas (tal vez su enrutador tenga asignada una /29 o varias /32)..
+
LibreQoS sabe cómo configurar estos dispositivos y en qué nodo (AP, sitio, etc.) se encuentran, gracias al archivo ShapedDevices.csv.
El archivo ShapedDevices.csv correlaciona las direcciones IP de los dispositivos con los circuitos (el servicio exclusivo de cada suscriptor de Internet).
+
A continuación se muestra un ejemplo de una entrada en el archivo ShapedDevices.csv:
+
+
+
Circuit ID
+
Circuit Name
+
Device ID
+
Device Name
+
Parent Node
+
MAC
+
IPv4
+
IPv6
+
Download Min Mbps
+
Upload Min Mbps
+
Download Max Mbps
+
Upload Max Mbps
+
Comment
+
+
+
+
10001
+
Person Name
+
10001
+
Device 1
+
AP_A
+
+
100.64.0.2, 100.64.0.8/29
+
fdd7:b724:0:100::/56
+
25
+
5
+
155
+
20
+
+
+
+
+
Si utiliza una de nuestras integraciones CRM, este archivo se generará automáticamente. Si no utiliza una integración, puede editar el archivo manualmente utilizando la interfaz de usuario web o editando directamente el archivo ShapedDevices.csv a través de la CLI.
Modifique el archivo ShapedDevices.csv utilizando su editor de hojas de cálculo preferido (LibreOffice Calc, Excel, etc.), siguiendo la plantilla del archivo - ShapedDevices.example.csv
+
Se requiere el ID del circuito. Debe ser una cadena de algún tipo (int está bien, se analiza como cadena). NO debe incluir ningún símbolo numérico (#). Cada circuito necesita un CircuitID único, no se pueden reutilizar. Aquí, circuito significa esencialmente la ubicación del cliente. Si un cliente tiene varias ubicaciones en diferentes partes de su red, utilice un CircuitID único para cada una de esas ubicaciones.
+
Se requiere al menos una dirección IPv4 o IPv6 para cada entrada.
+
El nombre del punto de acceso o del sitio debe configurarse en el campo Nodo principal. El campo Nodo principal puede dejarse en blanco para redes planas.
+
El archivo ShapedDevices.csv le permite establecer el ancho de banda mínimo garantizado y máximo permitido por suscriptor.
+
Las tarifas mínimas permitidas para los Circuitos son de 2 Mbit. El ancho de banda mínimo y máximo deben estar por encima de ese umbral.
+
Recomendación: establezca el ancho de banda mínimo en algo así como 25/10 y el máximo en 1,15 veces la velocidad anunciada en el plan utilizando bandwidthOverheadFactor = 1,15
+
+
De esta manera, cuando un punto de acceso alcanza su límite máximo, los usuarios disponen de la capacidad restante del punto de acceso distribuida de forma equitativa entre ellos.
+
Garantizar un ancho de banda mínimo razonable para cada suscriptor, permitiéndoles utilizar hasta el máximo proporcionado cuando la utilización del punto de acceso sea inferior al 100 %.
+
+
+
+
Nota sobre los SLA: para los clientes con contratos SLA que les garantizan un ancho de banda mínimo, establezca la tarifa de su plan como el ancho de banda mínimo. De esta forma, cuando un punto de acceso se acerque a su límite máximo, los clientes con SLA siempre obtendrán esa cantidad.
+
+
Una vez completada la configuración, ya está listo para ejecutar la aplicación e iniciar los Deamons
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/docs-es/v2.0/Quickstart/quickstart-libreqos-2.0.html b/_build/html/docs-es/v2.0/Quickstart/quickstart-libreqos-2.0.html
new file mode 100644
index 00000000..98e558ab
--- /dev/null
+++ b/_build/html/docs-es/v2.0/Quickstart/quickstart-libreqos-2.0.html
@@ -0,0 +1,164 @@
+
+
+
+
+
+
+
+
+ Install LibreQoS 1.5/2.0 — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Disable hyperthreading on the BIOS/UEFI of your host system. Hyperthreaading is also known as Simultaneous Multi Threading (SMT) on AMD systems. Disabling this is very important for optimal performance of the XDP cpumap filtering and, in turn, throughput and latency.
+
+
Boot, pressing the appropriate key to enter the BIOS settings
+
For AMD systems, you will have to navigate the settings to find the “SMT Control” setting. Usually it is under something like Advanced->AMDCBS->CPUCommonOptions->ThreadEnablement->SMTControl Once you find it, switch to “Disabled” or “Off”
+
For Intel systems, you will also have to navigate the settings to find the “hyperthrading” toggle option. On HP servers it’s under SystemConfiguration>BIOS/PlatformConfiguration(RBSU)>ProcessorOptions>Intel(R)HyperthreadingOptions.
If you use a Mellanox network card, the Ubuntu Server installer will ask you whether to install the mellanox/intel NIC drivers. Check the box to confirm. This extra driver is important.
+
On the Networking settings step, it is recommended to assign a static IP address to the management network interface.
+
Ensure SSH server is enabled so you can more easily log into the server later.
+
You can use scp or sftp to access files from your LibreQoS server for easier file editing. Here’s how to access via scp or sftp using an Ubuntu or Windows machine.
There are two options for the bridge to pass data through your two interfaces:
+
+
Option A: Regular Linux Bridge
+
Option B: Bifrost XDP-Accelerated Bridge
+
+
The regular Linux bridge is recommended for Nvidia/Mellanox NICs such as the ConnectX-5 series (which have superior bridge performance), and VM setups using virtualized NICs. The Bifrost Bridge is recommended for Intel NICs with XDP support, such as the X520 and X710.
+
To use the Bifrost bridge, be sure to enable Bifrost/XDP in lqos.conf in the Configuration section.
+
Below are the instructions to configure Netplan, whether using the Linux Bridge or Bifrost XDP bridge:
Option A: Netplan config for a regular Linux bridge
+
Ubuntu Server uses NetPlan, which uses .yaml files in /etc/netplan to determine interface settings.
+Here, we will add a .yaml specifically for LibreQoS - that way it is not overwritten when changes are made to the default .yaml file.
+
sudonano/etc/netplan/libreqos.yaml
+
+
+
Assuming your interfaces are ens19 and ens20, here is what your file would look like:
Please be sure to replace ens19 and ens20 in the example above with the correct shaping interfaces. The order of the interfaces does not matter for this section.
+
+
By setting dhcp4:no and dhcp6:no, the interfaces will be brought up as part of the normal boot cycle, despite not having IP addresses assigned.
Option B: Netplan config for the Bifrost XDP bridge
+
Ubuntu Server uses NetPlan, which uses .yaml files in /etc/netplan to determine interface settings.
+Here, we will add a .yaml specifically for LibreQoS - that way it is not overwritten when changes are made to the default .yaml file.
+
sudonano/etc/netplan/libreqos.yaml
+
+
+
Assuming your interfaces are ens19 and ens20, here is what your file would look like:
Please be sure to replace ens19 and ens20 in the example above with the correct shaping interfaces. The order of the interfaces does not matter for this section.
+
+
By setting dhcp4:no and dhcp6:no, the interfaces will be brought up as part of the normal boot cycle, despite not having IP addresses assigned.
If the status of one of the two services shows ‘failed’, examine why using journalctl, which shows the full status of the service. For example, if lqosd failed, you would run:
+
sudojournalctl-ulqosd-b
+
+
+
Press the End key on the keyboard to take you to the bottom of the log to see the latest updates to that log.
+
Lqosd will provide specific reasons it failed, such as an interface not being up, an interface lacking multi-queue, or other cocnerns.
We ask that you please share an anonymized screenshot of your LibreQoS deployment before (monitor only mode) and after (queuing enabled) to the LibreQoS Chat. This helps us gauge the impact of our software. It also makes us smile.
+
+
Enable monitor only mode
+
Run for 1 week
+
Disable monitor only mode
+
Toggle “Redact” to hide customer info in the LTS WebUI
When Rust finishes installing, it will tell you to execute a command to place the Rust build tools into your path. You need to either execute this command or logout and back in again.
+
Once that’s done, please run:
+
cd/opt/libreqos/src/
+./build_rust.sh
+
+
+
This will take a while the first time, but it puts everything in the right place.
You can now point a web browser at http://a.b.c.d:9123 (replace a.b.c.d with the management IP address of your shaping server) and enjoy a real-time view of your network.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/docs-es/v2.0/TechnicalDocs/integrations.html b/_build/html/docs-es/v2.0/TechnicalDocs/integrations.html
new file mode 100644
index 00000000..4a97183f
--- /dev/null
+++ b/_build/html/docs-es/v2.0/TechnicalDocs/integrations.html
@@ -0,0 +1,308 @@
+
+
+
+
+
+
+
+
+ Integrations — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
The Splynx Integration uses Basic authentication. For using this type of authentication, please make sure you enable Unsecure access in your Splynx API key settings. Also the Splynx API key should be granted access to the necessary permissions.
+
+
Tariff Plans -> Internet -> view
+
Tariff Plans -> Bundle -> view
+
Tariff Plans -> One time -> view
+
Tariff Plans -> Recurring -> view
+
FUP -> Counter -> view
+
FUP -> Compiler -> view
+
FUP -> Policies -> view
+
FUP -> Capped Data -> view
+
FUP -> CAP Tariff -> view
+
FUP -> FUP Limits -> view
+
FUP -> Traffic Usage -> view
+
Customers -> customer -> view
+
Customers -> customer information -> view
+
Customers -> Customers online -> view
+
Customers -> customer bundle services -> view
+
Customers -> customer internet services -> view
+
Customers -> traffic counter -> view
+
Customers -> customer recurring services -> view
+
Customers -> bonus traffic counter -> view
+
Customers -> CAP history -> view
+
Networking -> routers -> view
+
Networking -> network sites >view
+
Networking -> router contention -> view
+
Networking -> IPv4 networks -> view
+
Networking -> IPv4 networks IP -> view
+
+
To test the Splynx Integration, use
+
python3integrationSplynx.py
+
+
+
On the first successful run, it will create a ShapedDevices.csv file and network.json.
+ShapedDevices.csv will be overwritten every time the Splynx integration is run.
+
To ensure the network.json is always overwritten with the newest version pulled in by the integration, please edit /etc/lqos.conf with the command sudonano/etc/lqos.conf.
+Edit the file to set the value of always_overwrite_network_json to true.
+Then, run sudosystemctlrestartlqosd.
+
You have the option to run integrationSplynx.py automatically on boot and every X minutes (set by the parameter queue_refresh_interval_mins), which is highly recommended. This can be enabled by setting enable_splynx=true under the [splynx_integration] section in /etc/lqos.conf.
+Once set, run sudosystemctlrestartlqos_scheduler.
You can also modify the the file integrationSplynxBandwidths.csv to override the default bandwidths for each Node (Site, AP).
+
A template is available in the /opt/libreqos/src folder. To utilize the template, copy the file integrationSplynxBandwidths.template.csv (removing the .template part of the filename) and set the appropriate information inside each file. For example, if you want to change the set bandwidth for a site, you would do:
First, set the relevant parameters for UISP (token, url, automatic_import_uisp, etc.) in /etc/lqos.conf.
+
# Whether to run the UISP integration automatically in the lqos_scheduler service
+enable_uisp=true
+
+# Your UISP API Access Token
+token=""
+
+# Your UISP URL (include https://, but omit anything past .com, .net, etc)
+url="https://uisp.your_domain.com"
+
+# The site here refers to the Root site you want UISP to base its topology "perspective" from.
+# Default value is a blank string.
+site="Site_name"
+
+# Strategy type. "full" is recommended. "flat" can be used if only client shaping is desired.
+strategy="full"
+
+# Suspension strategy:
+# * "none" - do not handle suspensions
+# * "ignore" - do not add suspended customers to the network map
+# * "slow" - limit suspended customers to 0.1 Mbps
+suspended_strategy="none"
+
+# UISP's reported AP capacities for AirMax can be a bit optimistic. For AirMax APs, we limit
+# to 65% of what UISP claims an AP's capacity is, by default. This is adjustable.
+airmax_capacity=0.65
+
+# UISP's reported AP capacities for LTU are more accurate, but to be safe we adjust to 95%
+# of those capacities. This is adjustable.
+ltu_capacity=0.95
+
+# If you want to exclude sites in UISP from appearing in your LibreQoS network.json, simply
+# include them here. For example, exclude_sites = ["Site_1", "Site_2"]
+exclude_sites=[]
+
+# If you use DHCPv6, and want to pull in IPv6 CIDRs corresponding to each customer's IPv4
+# address, you can do so with this. If enabled, be sure to fill out mikrotikDHCPRouterList.csv
+# and run `python3 mikrotikFindIPv6.py` to test its functionality.
+ipv6_with_mikrotik=false
+
+# If you want customers to recieve a bit more of less than their allocated speed plan, set
+# it here. For example, 1.15 is 15% above their alloted speed plan.
+bandwidth_overhead_factor=1.15
+
+# By default, the customer "minimum" is set to 98% of the maximuum (CIR).
+commit_bandwidth_multiplier=0.98
+exception_cpes=[]
+
+# If you have some sites branched off PtMP Access Points, set `true`
+use_ptmp_as_parent=true
+
On the first successful run, it will create a network.json and ShapedDevices.csv file.
+If a network.json file exists, it will not be overwritten, unless you set always_overwrite_network_json=true.
+
ShapedDevices.csv will be overwritten every time the UISP integration is run.
+
To ensure the network.json is always overwritten with the newest version pulled in by the integration, please edit /etc/lqos.conf with the command sudonano/etc/lqos.conf.
+Edit the file to set the value of always_overwrite_network_json to true.
+Then, run sudosystemctlrestartlqosd.
+
You have the option to run integrationUISP.py automatically on boot and every X minutes (set by the parameter queue_refresh_interval_mins), which is highly recommended. This can be enabled by setting enable_uisp=true in /etc/lqos.conf. Once set, run sudosystemctlrestartlqos_scheduler.
You can also modify the the following files to more accurately reflect your network:
+
+
integrationUISPbandwidths.csv
+
integrationUISProutes.csv
+
+
Each of the files above have templates available in the /opt/libreqos/src folder. If you don’t find them there, you can navigate here. To utilize the template, copy the file (removing the .template part of the filename) and set the appropriate information inside each file.
+For example, if you want to change the set bandwidth for a site, you would do:
Say you have Site 1, Site 2, and Site 3.
+A backup path exists between Site 1 and Site 3, but is not the preferred path.
+Your preference is Site 1 > Site 2 > Site 3, but the integration by default connects Site 1 > Site 3 directly.
+
To fix this, add a cost above the default for the path between Site 1 and Site 3.
+
Site1,Site3,100
+
+
+
With this, data will flow Site 1 > Site 2 > Site 3.
+
To make the change, perform a reload of the integration with sudosystemctlrestartlqos_scheduler.
First, set the relevant parameters for Powercode (powercode_api_key, powercode_api_url, etc.) in /etc/lqos.conf.
+
To test the Powercode Integration, use
+
python3integrationPowercode.py
+
+
+
On the first successful run, it will create a ShapedDevices.csv file.
+You can modify the network.json file manually to reflect Site/AP bandwidth limits.
+ShapedDevices.csv will be overwritten every time the Powercode integration is run.
+You have the option to run integrationPowercode.py automatically on boot and every X minutes (set by the parameter queue_refresh_interval_mins), which is highly recommended. This can be enabled by setting enable_powercode=true in /etc/lqos.conf.
First, set the relevant parameters for Sonar (sonar_api_key, sonar_api_url, etc.) in /etc/lqos.conf.
+
To test the Sonar Integration, use
+
python3integrationSonar.py
+
+
+
On the first successful run, it will create a ShapedDevices.csv file.
+If a network.json file exists, it will not be overwritten, unless you set always_overwrite_network_json=true.
+You can modify the network.json file to more accurately reflect bandwidth limits.
+ShapedDevices.csv will be overwritten every time the Sonar integration is run.
+You have the option to run integrationSonar.py automatically on boot and every X minutes (set by the parameter queue_refresh_interval_mins), which is highly recommended. This can be enabled by setting enable_sonar=true in /etc/lqos.conf.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/docs-es/v2.0/TechnicalDocs/performance-tuning.html b/_build/html/docs-es/v2.0/TechnicalDocs/performance-tuning.html
new file mode 100644
index 00000000..9222ef43
--- /dev/null
+++ b/_build/html/docs-es/v2.0/TechnicalDocs/performance-tuning.html
@@ -0,0 +1,163 @@
+
+
+
+
+
+
+
+
+ Performance Tuning — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
The WebUI is controlled by the lqosd service. Usually, when the WebUI doesn’t start, it is related to lqosd being in a failed state.
+Check to see if the lqosd service is running:
+
sudosystemctlstatuslqosd
+
+
+
If the status is ‘failed’, examine why using journalctl, which shows the full status of the service:
+
journalctl-ulqosd--since"10 minutes ago"
+
+
+
Press the End key on the keyboard to take you to the bottom of the log to see the latest updates to that log.
+
Lqosd will provide specific reasons it failed, such as an interface not being up, an interface lacking multi-queue, or other cocnerns.
In /etc/lqos.conf, ensure that to_internet and to_network are set correctly. If not, simply swap the interfaces between those and restart lqosd and the scheduler.
+
sudosystemctlrestartlqosdlqos_scheduler
+
+
+
Make sure your services are running properly
+
sudosystemctlstatuslqosdlqos_scheduler
+
+
+
The service lqos_scheduler is dependent on the lqosd service being in a healthy, running state.
At the command-line, run sudoRUST_LOG=info/opt/libreqos/src/bin/lqosd which runs lqosd manually, and will provide specifics regarding why it failed to start.
This tends to show up when the MQ qdisc cannot be added correctly to the NIC interface. This would suggest the NIC has insufficient RX/TX queues. Please make sure you are using the recommended NICs.
The console output from running LibreQoS.py directly provides more specific errors regarding issues with ShapedDevices.csv and network.json
+Once you have identified the error and fixed ShapedDevices.csv and/or Network.json, please then run
+
sudosystemctlstartlqos_scheduler
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/docs-es/v2.0/Updates/update.html b/_build/html/docs-es/v2.0/Updates/update.html
new file mode 100644
index 00000000..9a0ec6d5
--- /dev/null
+++ b/_build/html/docs-es/v2.0/Updates/update.html
@@ -0,0 +1,168 @@
+
+
+
+
+
+
+
+
+ Actualización a la última versión — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Si usa el puente XDP, el tráfico dejará de pasar brevemente a través del puente cuando se reinicie lqosd (el puente XDP solo funciona mientras se ejecuta lqosd).
Hay dos opciones para que el puente pase datos entre las dos interfaces:
+
+
Opción A: Puente Regular de Linux (Recomendado)
+
Opción B: Puente Bifrost Acelerado con XDP
+
+
El puente regular de Linux es recomendado para la mayoría de las instalaciones. El puente de Linux continúa transfiriendo datos incluso si el servicio lqosd entra en un estado fallido, lo que lo hace una opción generalmente más segura para escenarios donde no hay una ruta de respaldo disponible. Funciona mejor con tarjetas de red Nvidia/Mellanox como las de la serie ConnectX-5 (que ofrecen un rendimiento superior en puentes) y configuraciones de máquinas virtuales con NICs virtualizadas. El puente Bifrost con XDP está recomendado para tarjetas de red Intel de 40G–100G que soportan XDP.
+
A continuación, se encuentran las instrucciones para configurar Netplan, ya sea usando el puente de Linux o el puente Bifrost con XDP:
+
+
+
Opción A: Configuración de Netplan para un puente regular de Linux (Recomendado)
+
Ubuntu Server utiliza Netplan, el cual se basa en archivos .yaml ubicados en /etc/netplan para determinar la configuración de interfaces.
+Aquí agregaremos un archivo .yaml específicamente para LibreQoS, de modo que no se sobrescriba cuando se hagan cambios al archivo .yaml por defecto.
+
sudonano/etc/netplan/libreqos.yaml
+
+
+
Asumiendo que sus interfaces de regulación son ens19 y ens20, su archivo se vería así:
Asegurese de reemplazar ens19 y ens20 en el ejemplo anterior con las interfaces reales que utilizará para regular el tráfico. El orden de las interfaces no importa en esta sección.
+
+
Al establecer dhcp4:no y dhcp6:no, las interfaces de regulación se activarán como parte del ciclo normal de arranque, aunque no tengan direcciones IP asignadas.
Opción B: Configuración de Netplan para el puente Bifrost con XDP
+
Ubuntu Server utiliza Netplan, el cual se basa en archivos .yaml ubicados en /etc/netplan para determinar la configuración de interfaces.
+Aquí agregaremos un archivo .yaml específicamente para LibreQoS, de modo que no se sobrescriba cuando se hagan cambios al archivo .yaml por defecto.
+
sudonano/etc/netplan/libreqos.yaml
+
+
+
Asumiendo que sus interfaces de regulación son ens19 y ens20, su archivo se vería así:
Asegurese de reemplazar ens19 y ens20 en el ejemplo anterior con las interfaces reales que utilizará para regular el tráfico. El orden de las interfaces no importa en esta sección.
+
+
Al establecer dhcp4:no y dhcp6:no, las interfaces de regulación se activarán como parte del ciclo normal de arranque, aunque no tengan direcciones IP asignadas.
La configuración para cada caja reguladora de LibreQoS se almacena en el archivo /etc/lqos.conf.
+
Edite el archivo para que coincida con su configuración usando:
+
sudonano/etc/lqos.conf
+
+
+
En la sección [bridge], cambie to_internet y to_network para que coincidan con sus interfaces de red.
+
+
to_internet="enp1s0f1"
+
to_network="enp1s0f2"
+
+
En la sección [bridge] del archivo lqos.conf, puede habilitar o deshabilitar el puente XDP con la opción use_xdp_bridge. El valor predeterminado es false - ya que la configuración por defecto asume un Puente Linux. Si eligió usar el puente XDP durante la configuración de requisitos previos, establezca use_xdp_bridge=true.
+
+
Configure downlink_bandwidth_mbps y uplink_bandwidth_mbps para que coincidan con el ancho de banda en Mbps de la conexión WAN/Upstream de su red. Lo mismo puede hacerse para generated_pn_download_mbps y generated_pn_upload_mbps.
+
to_internet es la interfaz que apunta hacia su router de borde (edge router) y el internet.
+
to_network es la interfaz que apunta hacia su router interno (core router) (o la red interna puenteada, si su red está configurada de esa manera).
+
+
Nota: Si observa que el tráfico no se está regulando cuando debería, asegúrese de invertir el orden de las interfaces y reiniciar lqosd y lqos_scheduler con: sudosystemctlrestartlqosdlqos_scheduler.
+
Después de cambiar cualquier parte de /etc/lqos.conf, se recomienda reiniciar siempre lqosd usando: sudosystemctlrestartlqosd. Esto integra los nuevos valores en lqos.conf, haciéndolos accesibles tanto para el código en Rust como en Python.
Network.json permite a los operadores de internet (ISP) definir una topología de red jerárquica o plana.
+
Si planea usar las integraciones ya incluidas en LibreQoS de UISP, Splynx o Netzur, no necesita todavía crear un archivo network.json.
+Si planea usar la integración ya incluida de UISP, el archivo network.json se creará en automático durante la primera ejecución (siempre y cuando network.json no exista previamente).
+
Si no planea usar una integración, puede definir manualmente el archivo network.json siguiendo el archivo de plantilla - network.example.json. A continuación se muestra una ilustración en tabla del network.example.json.
+
Entire Network
Site_1
Site_2
AP_A
Site_3
Pop_1
AP_1
PoP_5
AP_7
AP_9
PoP_6
AP_11
+
Para redes sin nodos padre (sin puntos de acceso o sitios estrictamente definidos), edita el network.json para usar una topología de red plana con:
LibreQoS soporta nodos virtuales en network.json para agrupar y para monitoreo/agregación en la WebUI/Insight. Los nodos virtuales no se incluyen en el árbol físico de shaping HTB (no crean clases HTB y no aplican límites de ancho de banda).
+
Para marcar un nodo como virtual, configura "virtual":true en ese nodo.
Durante el shaping, los nodos virtuales se eliminan y sus hijos se promueven al ancestro no virtual más cercano (revisa queuingStructure.json para el plan físico activo).
+
ShapedDevices.csv aún puede usar un nodo virtual como ParentNode para mostrar/agrupar; LibreQoS adjuntará esos circuitos para shaping al ancestro no virtual más cercano (si el nodo virtual está en el nivel superior y no tiene ancestro no virtual, se tratará como sin nodo padre para el shaping).
+
Evita colisiones de nombres después de la promoción (dos nodos con el mismo nombre terminando al mismo nivel).
para convertir manualNetwork.csv en un archivo network.json.
+manualNetwork.csv puede copiarse desde el archivo de plantilla manualNetwork.template.csv.
+
Nota: El nombre del nodo padre debe coincidir con el nombre usado para los clientes en ShapedDevices.csv.
LibreQoS regula dispositivos individuales por sus direcciones IP, las cuales son agrupadas en “circuitos”.
+
Un circuito representa el servicio de internet de un suscriptor de la operadora de internet, el cual puede tener solo una IP asociada (por ejemplo, el router del suscriptor puede tener asignada una sola IPv4 /32) o puede tener asignado varias IPs (quizás su router tenga asignado un /29, o varias /32).
+
El archivo ShapedDevices.csv correlaciona direcciones IP de dispositivos con circuitos (el servicio único de cada suscriptor de internet).
Si está utilizando una de nuestras integraciones con CRM, este archivo se generará automáticamente. Si no está utilizando una integración, puede editar el archivo manualmente usando la interfaz WebUI o editando directamente el archivo ShapedDevices.csv a través de la CLI.
Si necesita listar múltiples IPv4 en el campo IPv4, o múltiples IPv6 en el campo IPv6, agregue una coma entre ellas. Si está editando con un editor CSV (LibreOffice Calc, Excel), el editor CSV automáticamente colocará comillas alrededor de los elementos separados por coma. Si usted está editando el archivo manualmente con un editor de texto como notepad o nano, por favor agregue comillas alrededor de las entradas separadas por coma.
+
2794,"6 Littleton Drive, Ringgold, GA 30736",5,Device5,AP_11,,100.64.0.5,"fdd7:b724:0:500::/56,fdd7:b724:0:600::/56",1,1,105,18,""
+
Modifique el archivo ShapedDevices.csv usando su editor de hojas de cálculo preferido (LibreOffice Calc, Excel, etc.), siguiendo el archivo de plantilla - ShapedDevices.example.csv.
+
El Circuit ID es obligatorio. El Circuit ID puede ser un número o texto. Este campo NO debe incluir símbolos de hashtag (#). Cada circuito requiere un Circuit ID único – no pueden reutilizarse. Aquí, “circuito” se refiere esencialmente al servicio de un cliente. Si un cliente tiene múltiples ubicaciones en diferentes partes de su red, use un Circuit ID único para cada una.
+
Se requiere al menos una dirección IPv4 o IPv6 para cada entrada.
+
El nombre del Punto de Acceso o Sitio debe establecerse en el campo Parent Node. Puede dejarse en blanco para redes planas.
+
El archivo ShapedDevices.csv le permite establecer el ancho de banda mínimo (garantizado) y el máximo permitido por suscriptor.
+
Los valores Download Min y Upload Min de cada circuito deben ser 1 Mbps o mayores. Generalmente, deberían configurarse en 1 Mbps por defecto.
+
Los valores Download Max y Upload Max de cada circuito deben ser 2 Mbps o mayores. Generalmente, corresponden al plan de velocidad contratado por el cliente.
+
Recomendación: configure el ancho de banda mínimo en 1/1 y el máximo en 1.15X la velocidad anunciada del plan:
+
+
De esta manera, cuando un AP alcance su límite, los usuarios tendrán la capacidad restante del AP distribuida equitativamente.
+
Al establecer el máximo en 1.15X la velocidad contratada, se incrementa la probabilidad de que el suscriptor vea un resultado satisfactorio en un test de velocidad, incluso si hay tráfico ligero en segundo plano en su circuito (como un video HD, actualizaciones de software, etc.).
+
Esto permite a los suscriptores usar hasta el limite máximo de su plan cuando el AP tiene capacidad disponible.
+
+
+
+
Nota sobre SLAs: Para clientes con contratos SLA, donde garantizan un ancho de banda mínimo, puede configurar el plan contratado como el ancho de banda mínimo. De esta manera, cuando un AP se acerque a su límite, los clientes con SLA siempre tendrán esa velocidad disponible. Asegúrese de que la suma de los anchos de banda mínimos de los circuitos conectados a un nodo padre no supere la capacidad total de ese nodo padre. Si esto ocurre, LibreQoS tiene un mecanismo de seguridad que reduce los mínimos a 1/1 para todos los circuitos afectados.
+
Una vez que su configuración esté completa, estará listo para ejecutar la aplicación e iniciar los servicios systemd
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/docs-es/v2.0/configuration-es.html b/_build/html/docs-es/v2.0/configuration-es.html
new file mode 100644
index 00000000..d6278318
--- /dev/null
+++ b/_build/html/docs-es/v2.0/configuration-es.html
@@ -0,0 +1,212 @@
+
+
+
+
+
+
+
+
+ Configurar LibreQoS — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Use esta página para operaciones diarias y configuración por WebUI. Use Referencia avanzada de configuración para edición directa de archivos y flujos centrados en CLI.
+
+
+
Configuración inicial mediante la herramienta de instalación (desde el .deb)
+
+
La herramienta de instalación configura puente, interfaces, ancho de banda, rangos IP y usuarios de WebUI.
+
Notas:
+
+
La herramienta se controla con teclado (Enter para seleccionar, Q para salir sin guardar).
LibreQoS se coloca en línea en el borde de la red, normalmente entre el router de borde (NAT, firewall) y el router o switch de distribución principal.
Si utilizas NAT/CG-NAT, coloca LibreQoS en línea antes del punto donde se aplica el NAT, ya que necesita regular las direcciones previas al NAT (100.64.0.0/12) y no las IP públicas posteriores.
LibreQoS puede analizar tráfico MPLS siempre que siga el patrón estándar:
+
(mplstags)(optionalvlantags)(ipheader)
+
+
+
Si tu despliegue MPLS usa un patrón distinto, lo ideal es terminar el tráfico MPLS en el router o switch de distribución principal antes de que llegue a LibreQoS.
Recomendamos usar protocolos como OSPF para definir rutas de bajo y alto costo entre el router de borde y el router/switch de distribución. La ruta de bajo costo debe pasar “a través” de las interfaces puente del shaper para que LibreQoS pueda observar y regular el tráfico. Por ejemplo, la ruta OSPF de bajo costo puede tener costo 1. El enlace de alto costo (respaldo) debe omitir por completo LibreQoS y configurarse con un costo mayor (por ejemplo 100 en OSPF) para que el tráfico solo tome ese camino cuando el puente de LibreQoS no esté operativo.
Una vez finalizada la instalación de Rust, se le indicará que ejecute un comando para añadir las herramientas de construcción de Rust a su variable de entorno PATH. Deberá ejecutar dicho comando o bien cerrar sesión y volver a iniciarla.
+
Después, ejecute lo siguiente:
+
cd/opt/libreqos/src/
+./build_rust.sh
+
+
+
Este proceso tomará algo de tiempo la primera vez, pero colocará todos los componentes en las ubicaciones correspondientes.
Ahora puede abrir un navegador web en http://a.b.c.d:9123 (reemplace a.b.c.d con la dirección IP de administración de su servidor de shaping) y disfrutar de una vista en tiempo real de su red.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/docs-es/v2.0/high-availability-es.html b/_build/html/docs-es/v2.0/high-availability-es.html
new file mode 100644
index 00000000..a634c991
--- /dev/null
+++ b/_build/html/docs-es/v2.0/high-availability-es.html
@@ -0,0 +1,226 @@
+
+
+
+
+
+
+
+
+ Alta Disponibilidad y Dominios de Falla — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Una ruta está activa (preferida) y otra está en respaldo (espera). La política de enrutamiento controla la selección de ruta y la conmutación por falla.
Si usa BGP, utilice controles de preferencia estándar para definir una ruta primaria y otra de respaldo (por ejemplo local preference, MED o AS path prepending según su diseño). Mantenga la política determinista y documentada.
Si tienes más de una caja reguladora (shaper), puedes elegir cuál visualizar desde el desplegable Shaper Nodes (ubicado justo debajo del cuadro de búsqueda).
Al hacer clic en el selector de tiempo (por defecto Last 24 Hours) puedes definir el rango que se mostrará, desde 15 minutos hasta 28 días. También es posible establecer periodos personalizados (Now minus X minutes) o ventanas muy específicas.
Permite identificar la topología general de la red desde la perspectiva de Insight. Al pasar el cursor por los enlaces se muestra el throughput y las retransmisiones TCP actuales de ese tramo.
Libby es el asistente IA de Insight. Puede ayudarte con dudas sobre LibreQoS o Insight basándose en la documentación oficial. Libby accede a datos en vivo y de largo plazo tanto de los shapers sincronizados como de Insight. Puede responder en la mayoría de los idiomas mediante traducción automática.
+
Si encuentras nuevos casos de uso para Libby, comparte con nosotros cómo te ayuda en el flujo de trabajo.
Esta vista entrega heatmaps de RTT, retransmisiones y capacidad para cada Access Point, OLT y sitio de tu red en una sola pantalla, lo que facilita detectar puntos problemáticos rápidamente.
Se basa en la vista Tree Overview de la WebUI de LibreQoS y muestra el diagrama Sankey a lo largo del tiempo para identificar cuellos de botella que afecten el rendimiento.
Insight permite generar reportes asistidos por IA sobre circuitos específicos. Estos informes usan los últimos 7 días de actividad del cliente (características por ASN, contexto de topología y contexto geográfico) e incluyen un Perfil de usuario, Hallazgos clave, Problemas críticos, Tendencias de rendimiento, una Recomendación de mejora y elementos sugeridos para revisión manual.
Las compilaciones actuales pueden cachear grants firmados localmente para que el nodo siga operando durante pérdidas temporales de conectividad con servicios de control de Insight. La validez y expiración del grant se aplica localmente.
+
Notas operativas:
+
+
Mantenga .keys/ persistente entre reinicios.
+
Trate .keys/ como material sensible.
+
Si hay estado inválido de grant/clave, lqosd mostrará errores de licencia/grant en logs.
+
+
+
+
Límites de circuitos mapeados y estado de licencia
+
Compilaciones recientes aplican límites de circuitos mapeados según estado de licencia.
+
Si su nodo está sin licencia/válido, LibreQoS puede aplicar un límite predeterminado de circuitos mapeados. Cuando se excede, los logs incluyen mensajes como:
+
+
Mappedcircuitlimitreached
+
Bakerymappedcircuitcapenforced
+
+
Cuando ocurra:
+
+
Revise estado de licencia Insight en la UI.
+
Revise journalctl-ulqosd para conteos requested/allowed/dropped.
+
Verifique si la cantidad de circuitos mapeados excede su licencia.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/docs-es/v2.0/integrations-es.html b/_build/html/docs-es/v2.0/integrations-es.html
new file mode 100644
index 00000000..a070824a
--- /dev/null
+++ b/_build/html/docs-es/v2.0/integrations-es.html
@@ -0,0 +1,200 @@
+
+
+
+
+
+
+
+
+ Integraciones CRM/NMS — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Use esta página para elegir y configurar integraciones CRM/NMS soportadas. Use las páginas por integración para detalles específicos.
+
La mayoría de operadores usan las integraciones incluidas. Si usa scripts propios como fuente de verdad para network.json y ShapedDevices.csv, comience por Modos de operación y fuente de verdad.
La mayoría de operadores usan este camino de integraciones incluidas.
+Si usa scripts propios como fuente de verdad para network.json y ShapedDevices.csv, comience por Modos de operación y fuente de verdad.
+
Comportamiento importante cuando hay integraciones habilitadas:
+
+
ShapedDevices.csv normalmente se regenera por los jobs de sincronización.
+
El comportamiento de sobrescritura de network.json depende de su configuración de integración (por ejemplo always_overwrite_network_json).
+
Las ediciones manuales pueden sobrescribirse en el próximo ciclo de refresco.
⚠️ Aviso de Cambio Importante: Antes de v1.5-RC-2, la estrategia predeterminada de Splynx era full. A partir de v1.5-RC-2, la estrategia predeterminada es ap_only para un mejor rendimiento del CPU. Si requiere el comportamiento anterior, configure explícitamente strategy="full" en su sección de configuración de Splynx.
+
+
Primero, configure los parámetros relevantes de Splynx (splynx_api_key, splynx_api_secret, etc.) en /etc/lqos.conf.
LibreQoS soporta múltiples estrategias de topología para la integración con Splynx, balanceando el rendimiento del CPU con las necesidades de jerarquía de red:
+
+
+
Estrategia
+
Descripción
+
Impacto CPU
+
Caso de Uso
+
+
+
+
flat
+
Solo regula suscriptores, sin jerarquía
+
Menor
+
Máximo rendimiento, regulación simple de suscriptores únicamente
+
+
ap_only
+
Una capa: AP → Clientes
+
Bajo
+
Predeterminado. Mejor balance entre rendimiento y estructura
+
+
ap_site
+
Dos capas: Sitio → AP → Clientes
+
Medio
+
Agregación a nivel de sitio con complejidad moderada
+
+
full
+
Mapeo completo de topología
+
Mayor
+
Representación completa de jerarquía de red
+
+
+
+
Configure la estrategia en /etc/lqos.conf bajo la sección [splynx]:
+
[splynx]
+# ... otras configuraciones de splynx ...
+strategy="ap_only"
+
+
+
Consideraciones de Rendimiento:
+
+
Las estrategias flat y ap_only reducen significativamente la carga del CPU al limitar la profundidad de la red
+
Elija ap_only para la mayoría de implementaciones a menos que necesite agregación de tráfico a nivel de sitio
+
Use full solamente si requiere representación completa de la topología de red y tiene recursos CPU adecuados
+
+
+
+
Promover Nodos a Raíz (Optimización de Rendimiento)
+
Cuando use la estrategia de topología full, puede encontrar cuellos de botella de rendimiento del CPU donde todo el tráfico fluye a través de un solo sitio raíz, limitando el throughput a lo que un solo núcleo de CPU puede manejar.
+
La función promote_to_root soluciona esto promoviendo sitios específicos a nodos de nivel raíz, distribuyendo la regulación de tráfico entre múltiples núcleos de CPU.
+
Configuración:
+
+
Navegue a Integración → Común en la interfaz web
+
En el campo “Promover Nodos a Raíz”, ingrese un nombre de sitio por línea:
La integración con Splynx utiliza autenticación Básica. Para usar este tipo de autenticación, asegúrese de habilitar el Acceso No Seguro en la configuración de su clave API de Splynx. Además, la clave API de Splynx debe tener los permisos adecuados.
+
+
+
Categoría
+
Nombre
+
Permiso
+
+
+
+
Tariff Plans
+
Internet
+
View
+
+
FUP
+
Compiler
+
View
+
+
FUP
+
Policies
+
View
+
+
FUP
+
Capped Data
+
View
+
+
FUP
+
CAP Tariff
+
View
+
+
FUP
+
FUP Limits
+
View
+
+
Customers
+
Customer
+
View
+
+
Customers
+
Customers Online
+
View
+
+
Customers
+
Customer Internet services
+
View
+
+
Networking
+
Routers
+
View
+
+
Networking
+
Router contention
+
View
+
+
Networking
+
MikroTik
+
View
+
+
Networking
+
Monitoring
+
View
+
+
Networking
+
Network Sites
+
View
+
+
Networking
+
IPv4 Networks
+
View
+
+
Networking
+
IPv4 Networks IP
+
View
+
+
Networking
+
CPE
+
View
+
+
Networking
+
CPE AP
+
View
+
+
Networking
+
IPv6 Networks
+
View
+
+
Networking
+
IPv6 Networks IP (Addresses)
+
View
+
+
Administration
+
Locations
+
View
+
+
+
+
Para probar la integración con Splynx, use:
+
python3integrationSplynx.py
+
+
+
En la primera ejecución exitosa, se crearán los archivos ShapedDevices.csv y network.json.
+ShapedDevices.csv será sobrescrito cada vez que se ejecute la integración con Splynx.
+
Para asegurarse de que network.json siempre se sobrescriba con la versión más reciente obtenida por la integración, edite /etc/lqos.conf con el comando sudonano/etc/lqos.conf y configure el valor always_overwrite_network_json a true.
+Luego ejecute sudosystemctlrestartlqosd.
+
Tiene la opción de ejecutar integrationSplynx.py automáticamente al iniciar el equipo y cada X minutos (configurado con el parámetro queue_refresh_interval_mins), lo cual es altamente recomendado. Esto se habilita estableciendo enable_splynx=true bajo la sección [splynx_integration] en /etc/lqos.conf.
+Una vez configurado, ejecute sudosystemctlrestartlqos_scheduler.
También puede modificar el archivo integrationSplynxBandwidths.csv para sobrescribir los anchos de banda predeterminados de cada Nodo (Sitio, AP).
+
Hay una plantilla disponible en la carpeta /opt/libreqos/src. Para usarla, copie el archivo integrationSplynxBandwidths.template.csv (eliminando la parte .template del nombre) y edítelo con la información correspondiente. Por ejemplo, si desea cambiar el bando de ancha de un sitio, ejecutaría:
Los despliegues de Netzur proporcionan un endpoint REST con información de zonas y clientes protegido con token Bearer. Configure la sección [netzur_integration] en /etc/lqos.conf:
enable_netzur habilita la importación automática desde lqos_scheduler.
+
api_key es el token Bearer generado dentro de Netzur.
+
api_url debe devolver un JSON con los arreglos zones (convertidos en sitios) y customers (convertidos en circuitos y dispositivos).
+
timeout_secs permite incrementar el tiempo de espera de la petición cuando el API responde lentamente (por defecto 60 segundos).
+
use_mikrotik_ipv6 agrega prefijos IPv6 obtenidos de mikrotikDHCPRouterList.csv.
+
+
Para una importación manual:
+
python3integrationNetzur.py
+
+
+
La integración actualiza ShapedDevices.csv y, salvo que always_overwrite_network_json esté deshabilitado, también network.json. Ajuste la opción Integración → Común si necesita preservar un network.json existente entre ejecuciones de Netzur.
Primero, configure los parámetros relevantes de VISP en /etc/lqos.conf:
+
[visp_integration]
+enable_visp=true
+client_id="su-client-id"
+client_secret="su-client-secret"
+username="usuario-app"
+password="password-app"
+# Opcional: si se deja vacío, se usa el primer ISP ID del token
+# isp_id = 0
+timeout_secs=20
+# Opcional: dominio para enriquecimiento de sesiones online
+# online_users_domain = ""
+
+
+
Notas:
+
+
La importación VISP usa GraphQL y actualmente trabaja en estrategia flat.
+
La integración reescribe ShapedDevices.csv en cada ejecución.
+
network.json solo se sobrescribe cuando always_overwrite_network_json=true (en [integration_common]).
+
Los tokens de VISP se cachean en <lqos_directory>/.visp_token_cache_*.json.
LibreQoS soporta múltiples estrategias de topología para la integración con UISP para equilibrar el rendimiento del CPU con las necesidades de jerarquía de red:
+
+
+
Estrategia
+
Descripción
+
Impacto en CPU
+
Caso de Uso
+
+
+
+
flat
+
Solo regula suscriptores por velocidad del plan de servicio
+
Mínimo
+
Máximo rendimiento, regulación simple solo de suscriptores
+
+
ap_only
+
Regula por plan de servicio y Punto de Acceso
+
Bajo
+
Buen equilibrio entre rendimiento y control a nivel de AP
+
+
ap_site
+
Regula por plan de servicio, Punto de Acceso y Sitio
+
Medio
+
Agregación a nivel de sitio con complejidad moderada
+
+
full
+
Regula toda la red incluyendo backhauls, Sitios, APs y clientes
+
Alto
+
Recomendado para la mayoría de implementaciones. Jerarquía completa de red con reconocimiento de backhaul
+
+
+
+
Cómo Elegir la Estrategia Correcta:
+
+
Use full para la mayoría de implementaciones para obtener reconocimiento completo de la topología de red incluyendo enlaces de backhaul
+
Use ap_site si necesita control a nivel de sitio pero no necesita regulación de backhaul
+
Use ap_only para mejor rendimiento cuando no se necesita agregación de sitios
+
Use flat solo cuando el máximo rendimiento es crítico y no necesita ninguna jerarquía
+
+
Nota de Rendimiento: Cuando use la estrategia full con redes grandes, considere usar la función promote_to_root (vea Promover Nodos a Raíz arriba) para distribuir la carga del CPU entre múltiples núcleos.
[uisp_integration]
+# Configuración Principal
+enable_uisp=true
+token="su-token-api-aqui"
+url="https://uisp.su_dominio.com"
+site="Nombre_Sitio_Raiz"# Sitio raíz para perspectiva de topología
+
+# Estrategia de Topología (ver tabla arriba)
+strategy="full"# Recomendado para la mayoría de implementaciones
+
+# Manejo de Suspensiones (ver tabla arriba)
+suspended_strategy="none"
+
+# Ajustes de Capacidad
+# Las capacidades de AP reportadas por UISP pueden ser optimistas
+airmax_capacity=0.65# Usar 65% de la capacidad reportada de AirMax
+ltu_capacity=0.95# Usar 95% de la capacidad reportada de LTU
+
+# Gestión de Sitios
+exclude_sites=[]# Sitios a excluir, ej: ["Sitio_Prueba", "Sitio_Lab"]
+use_ptmp_as_parent=true# Para sitios conectados a través de APs PtMP
+
+# Ajustes de Ancho de Banda
+bandwidth_overhead_factor=1.15# Dar a clientes 15% sobre velocidad del plan
+commit_bandwidth_multiplier=0.98# Establecer mínimo al 98% del máximo (CIR)
+
+# Opciones Avanzadas
+ipv6_with_mikrotik=false# Habilitar si usa DHCPv6 con MikroTik
+always_overwrite_network_json=false# Establecer true para reconstruir topología en cada ejecución
+exception_cpes=[]# Excepciones de CPE en formato ["cpe:parent"]
+squash_sites=[]# Opcional: sitios a compactar
+enable_squashing=false# Opcional: habilita lógica adicional de compactación
+do_not_squash_sites=[]# Opcional: sitios excluidos de compactación
+ignore_calculated_capacity=false# Opcional: prioriza capacidad configurada sobre la calculada
+insecure_ssl=false# Opcional: ignora validación TLS del API UISP
+
En la primera ejecución exitosa, se crearán los archivos network.json y ShapedDevices.csv.
+Si ya existe un archivo network.json, no será sobrescrito a menos que configure always_overwrite_network_json=true.
+
ShapedDevices.csv será sobrescrito cada vez que se ejecute la integración de UISP.
+
Para asegurarse de que network.json siempre sea sobrescrito con la versión más reciente obtenida por la integración, edite el archivo /etc/lqos.conf con el comando sudonano/etc/lqos.conf y configure el valor always_overwrite_network_json a true.
+Luego ejecute: sudosystemctlrestartlqosd.
+
Tiene la opción de ejecutar integrationUISP.py automáticamente al iniciar el equipo y cada X minutos (configurado con el parámetro queue_refresh_interval_mins), lo cual es altamente recomendado. Esto se habilita estableciendo enable_uisp=true en /etc/lqos.conf. Una vez configurado, ejecute sudosystemctlrestartlqos_scheduler.
También puede modificar los siguientes archivos para reflejar su red con mayor precisión:
+
+
integrationUISPbandwidths.csv
+
integrationUISProutes.csv
+
+
Cada uno de los archivos mencionados arriba tienen plantillas, las cuales están disponibles en la carpeta /opt/libreqos/src. Si no los encuentra, puede obtenerlos aquí. Para utilizarlos, copie el archivo (eliminando la parte .template del nombre) y edítelo con la información correspondiente.
+Por ejemplo, si desea cambiar el bando de ancha de un sitio, ejecutaría:
El costo predeterminado entre nodos suele ser 10. La integración genera un archivo de gráfico en formato dot: /opt/libreqos/src/graph.dot el cuál puede visualizarse con Graphviz. Esto genera un mapa con los costos de todos los enlaces.
+
+
Ejemplo:
+Tiene Sitio 1, Sitio 2 y Sitio 3.
+Existe un camino de respaldo entre Sitio 1 y Sitio 3, pero no es el preferido.
+El camino preferido debería ser: Sitio 1 > Sitio 2 > Sitio 3, pero la integración conecta directamente Sitio 1 > Sitio 3 por predeterminado.
+
Para solucionar esto, agregue un costo mayor al predeterminado entre Sitio 1 y Sitio 3:
+
Site1,Site3,100
+Site3,Site1,100
+
+
+
De esta forma, el tráfico seguirá el camino: Sitio 1 > Sitio 2 > Sitio 3.
+
Para aplicar el cambio, reinicie la integración ejecutando: sudosystemctlrestartlqos_scheduler.
Si la sección no existe, agréguela copiando el bloque anterior.
+Después, configure los valores apropiados para wispgate_api_token y wispgate_api_url, luego guarde el archivo.
+
Para probar la integración con WISPGate, ejecute:
+
python3integrationWISPGate.py
+
+
+
En la primera ejecución exitosa, se crearán los archivos network.json y ShapedDevices.csv.
+ShapedDevices.csv será sobrescrito cada vez que se ejecute la integración de WISPGate.
+
Para asegurarse de que network.json siempre sea sobrescrito con la versión más reciente obtenida por la integración, edite el archivo /etc/lqos.conf con el comando sudonano/etc/lqos.conf y configure el valor always_overwrite_network_json a true.
+Luego ejecute: sudosystemctlrestartlqosd.
+
Tiene la opción de ejecutar integrationWISPGate.py automáticamente al iniciar el equipo y cada X minutos (configurado con el parámetro queue_refresh_interval_mins), lo cual es altamente recomendado. Esto se habilita estableciendo enable_wispgate=true en /etc/lqos.conf. Una vez configurado, ejecute sudosystemctlrestartlqos_scheduler.
Primero, configure los parámetros relevantes de Powercode (powercode_api_key, powercode_api_url, etc.) en /etc/lqos.conf.
+
Para probar la integración con Powercode, ejecute:
+
python3integrationPowercode.py
+
+
+
En la primera ejecución exitosa, se creará el archivo ShapedDevices.csv.
+Puede modificar el archivo network.json manualmente para reflejar los límites de ancho de banda de los Sitios/AP.
+El archivo ShapedDevices.csv se sobrescribirá cada vez que se ejecute la integración de Powercode.
+Tiene la opción de ejecutar integrationPowercode.py automáticamente al iniciar el equipo y cada X minutos (configurado con el parámetro queue_refresh_interval_mins), lo cual es altamente recomendado. Esto se habilita estableciendo enable_powercode=true en /etc/lqos.conf.
Primero, configure los parámetros relevantes de Sonar (sonar_api_key, sonar_api_url, etc.) en /etc/lqos.conf.
+
Para probar la integración con Sonar, ejecute:
+
python3integrationSonar.py
+
+
+
En la primera ejecución exitosa, se crearán los archivos network.json y ShapedDevices.csv.
+Si ya existe un archivo network.json, no será sobrescrito a menos que configure always_overwrite_network_json=true.
+Puede modificar el archivo network.json para reflejar con mayor precisión los límites de ancho de banda.
+El archivo ShapedDevices.csv se sobrescribirá cada vez que se ejecute la integración de Sonar.
+Tiene la opción de ejecutar integrationSonar.py automáticamente al iniciar el equipo y cada X minutos (configurado con el parámetro queue_refresh_interval_mins), lo cual es altamente recomendado. Esto se habilita estableciendo enable_sonar=true en /etc/lqos.conf.
Jesync UI Tool Dashboard es un panel de control moderno, basado en la web, diseñado para facilitar, agilizar y hacer más amigable la gestión de LibreQoS y de sus archivos de integración.
Este script automatiza la sincronización de los secretos PPP de MikroTik (por ejemplo, usuarios PPPoE) y los usuarios activos de hotspot con un archivo CSV compatible con LibreQoS (ShapedDevices.csv). Supervisa continuamente el router MikroTik para detectar cambios en los secretos PPP y en los usuarios activos de hotspot, como adiciones, actualizaciones o eliminaciones, y actualiza el archivo CSV en consecuencia.
+El script también calcula los límites de velocidad (descarga/carga) según el perfil PPP asignado y garantiza que el archivo CSV siempre esté actualizado.
+
El script está diseñado para ejecutarse como un servicio en segundo plano utilizando systemd, asegurando que se inicie automáticamente al arrancar el sistema y se reinicie en caso de algún fallo.
Use esta página para elegir y aplicar su política de fuente de verdad (integraciones incluidas vs fuente personalizada) antes de cambios en producción.
+
LibreQoS soporta dos modos de operación principales.
+
+
+
Integraciones incluidas (recomendado para la mayoría de operadores)
+
En este modo, su CRM/NMS es la fuente de verdad y los jobs de integración de LibreQoS generan los insumos de shaping.
+
Comportamiento clave:
+
+
ShapedDevices.csv se regenera en ciclos de sincronización.
+
El comportamiento de sobrescritura de network.json depende de la configuración de integración (por ejemplo always_overwrite_network_json).
+
Las ediciones manuales directas pueden sobrescribirse en el siguiente refresco del scheduler.
Desactiva el Hyper-Threading en la BIOS/UEFI de tu sistema host. El Hyper-Threading también se conoce como Simultaneous Multi Threading (SMT) en sistemas AMD. Desactivarlo es muy importante para obtener un rendimiento óptimo del filtrado cpumap con XDP y, por ende, mejorar el rendimiento y la latencia.
+
+
Inicia el sistema y presiona la tecla correspondiente para entrar a la configuración de la BIOS.
+
En sistemas AMD, deberás navegar por las opciones hasta encontrar la opción llamada “SMT Control”. Normalmente se encuentra en: Advanced->AMDCBS->CPUCommonOptions->ThreadEnablement->SMTControl Una vez localizada, cambia la opción a “Disabled” o “Off”.
+
En sistemas Intel, también deberás buscar la opción para desactivar el Hyper-Threading en ajustes. En servidores HP, por ejemplo, está ubicada en: SystemConfiguration>BIOS/PlatformConfiguration(RBSU)>ProcessorOptions>Intel(R)HyperthreadingOptions
SR-IOV puede desactivar XDP nativo (modo controlador) en las Funciones Físicas (PF), forzando XDP Genérico (SKB) y reduciendo el rendimiento y la estabilidad de LibreQoS. Desactive SR-IOV en la BIOS/UEFI para las tarjetas de red (NIC) utilizadas por LibreQoS. Si existen opciones por ranura/por puerto, desactívelas.
Para las máquinas virtuales Proxmox, se requiere el paso a través de la tarjeta de red (NIC) para alcanzar un rendimiento superior a 10 Gbps (XDP vs. XDP genérico).
+
LibreQoS requiere dos o más colas RX/TX, por lo que al usar Proxmox, asegúrese de habilitar Multicola para las interfaces de modelado asignadas a la máquina virtual. La multicola debe tener un valor igual al número de núcleos de vCPU asignados a la máquina virtual.
Suplantación de MAC en Hyper-V (Si está dentro de una máquina virtual)
+
Si su sistema LibreQoS se ejecuta dentro de Hyper-V y ha conectado dos vNIC (eth1, eth2), Hyper-V bloqueará el tráfico del puente porque este genera tramas con direcciones MAC diferentes a la asignada a la vNIC. Para solucionar esto en un host Windows:
LibreQoS puede ejecutarse en un servidor físico dedicado (bare metal) o como una máquina virtual (VM). El sistema operativo soportado es Ubuntu Server 24.04.
Eliga una CPU con alto rendimiento de un solo hilo dentro de su presupuesto. El regulamiento es intensivo en CPU y requiere alto rendimiento en un solo hilo.
+
+
El rendimiento de un solo hilo determina la capacidad máxima de un único HTB (núcleo de CPU). Esto, a su vez, afecta la capacidad máxima de cualquier nodo de nivel superior en la jerarquía de red (por ejemplo, sitios principales en su red). También impacta la velocidad máxima de plan que puede ofrecer a sus clientes dentro de márgenes seguros.
+
+
+
Puntaje Single-Thread
+
Nodo Superior Máx.
+
Plan de Cliente Máx
+
+
+
+
1000
+
1 Gbps
+
100 Mbps
+
+
1500
+
2 Gbps
+
500 Mbps
+
+
2000
+
3 Gbps
+
1 Gbps
+
+
3000
+
4 Gbps
+
2 Gbps
+
+
4000
+
5 Gbps
+
3 Gbps
+
+
+
+
A continuación se muestra una tabla de la capacidad agregada aproximada, suponiendo que una CPU tenga una puntuación de rendimiento de un solo hilo de 1000, 2000, 3000 o 4000:
Se recomienda desactivar Hyper-Threading (Simultaneous Multi-Threading) en la configuración del BIOS/UEFI, ya que puede interferir con el procesamiento de XDP.
Al igual que con cualquier máquina que ejecute LibreQoS, asegúrese de desactivar Hyper-Threading. Específicamente para el MS-01, considere reemplazar la pasta térmica para reducir la temperatura de la CPU en aproximadamente 20 grados centígrados (Nota: esto puede anular la garantía).
Otra solución rentable es adquirir un servidor usado de un proveedor de confianza, como TheServerStore.
+Estos proveedores suelen ofrecer servidores capaces de manejar un rendimiento de 10 Gbps, por alrededor de 500 USD.
Una interfaz de red de administración completamente separada de las interfaces de regulamiento de tráfico. Usualmente esta sería la interfaz Ethernet integrada en la placa base.
+
Una Tarjeta de Red Dedicada para Dos Interfaces de Regulamiento
+
+
Las Tarjetas de Red oficialmente soportadas para las dos interfaces de regulamiento se enumeran a continuación:
(*) Intel suele bloquear por fabricante la compatibilidad de módulos SFP+. Verifique la compatibilidad del módulo antes de comprar. Mellanox no presenta este problema.
+
ÚNICAMENTE brindaremos soporte para sistemas que utilicen una NIC de la lista anterior.
+Algunas otras NICs podrían funcionar, pero no estarán oficialmente soportadas por LibreQoS.
+Si deseas probar la compatibilidad de otra tarjeta, ten en cuenta estos requisitos fundamentales de NIC:
LibreQoS puede ejecutarse como una máquina virtual (VM), aunque esto implica una penalización de rendimiento del 30%. Para VMs, se requiere “atravesamiento de NIC” para alcanzar un rendimiento superior a 10 Gbps (XDP vs XDP genérico).
+LibreQoS requiere 2 o más filas RX/TX, por lo que al usar una plataforma de virtualización como Proxmox, asegúrese de habilitar Multiqueue para las interfaces de regulamiento asignadas a la VM. El valor de “Multiqueue” debe ser igual al número de núcleos vCPU asignados a la VM.
+
+
+
Rendimiento
+
vCPU*
+
RAM
+
Disco
+
+
+
+
1 Gbps
+
2
+
8 GB
+
50 GB
+
+
10 Gbps
+
8
+
32 GB
+
50 GB
+
+
+
+
+
Se asume un rendimiento de vCPU igual al de un único núcleo del Intel Xeon E-2456 con “hyper-threading” deshabilitado.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/docs-es/v2.0/scale-topology-es.html b/_build/html/docs-es/v2.0/scale-topology-es.html
new file mode 100644
index 00000000..605dfdaf
--- /dev/null
+++ b/_build/html/docs-es/v2.0/scale-topology-es.html
@@ -0,0 +1,236 @@
+
+
+
+
+
+
+
+
+ Escalado y diseño de topología — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Te pedimos que compartas una captura anonimizada de tu despliegue de LibreQoS antes (modo monitor) y después (colas activadas) en el LibreQoS Chat. Esto nos ayuda a medir el impacto del software y, de paso, nos saca una sonrisa.
+
+
Activa el modo monitor only.
+
Déjalo ejecutándose durante 1 semana.
+
Desactiva el modo monitor only.
+
Activa la opción Redact en la WebUI de LTS para ocultar datos sensibles.
StormGuard es el subsistema de ajuste adaptativo de colas de LibreQoS para eventos de congestión y calidad.
+
+
Advertencia importante de alcance
+StormGuard está pensado para casos de uso específicos, como controlar congestión en enlaces WAN de ancho de banda variable (por ejemplo redes marítimas), o para un número pequeño de puntos de acceso con capacidades muy variables.
+No está pensado para gestionar decenas o cientos de nodos al mismo tiempo.
Corrija errores en ShapedDevices.csv y/o network.json, luego:
+
sudosystemctlstartlqos_scheduler
+
+
+
+
+
Flow Map / Tree Overview / ASN Explorer aparecen en blanco
+
Algunas vistas requieren suficiente dato reciente para renderizar.
+
+
Confirme que lqosd está saludable.
+
Espere acumulación de tráfico.
+
Recargue la página tras 1-2 minutos.
+
Revise logs:
+
+
journalctl-ulqosd--since"10 minutes ago"
+
+
+
Si sigue en blanco con tráfico normal, recolecte logs y abra issue.
+
+
+
Colisión de promoción de nodo virtual (network.json)
+
Si LibreQoS.py falla con Virtualnodepromotioncollision:'AP_A'alreadyexistsatthislevel., hay un nodo con "virtual":true cuyos hijos colisionan por nombre al promoverse.
+
Renombre nodos en conflicto o reestructure jerarquía para evitar colisiones.
Puedes descargar Ubuntu Server 24.04 LTS desde aquí.
+Por el momento, solo se admite Ubuntu Server 24.04. Asegúrate de no utilizar otras versiones.
+
+
Arranca Ubuntu Server desde una USB.
+
Sigue los pasos a continuación para instalar Ubuntu Server.
+
+
+
+
+
Para las interfaces de red, desactiva completamente las interfaces utilizadas. Después, asigna una dirección IP estática a la interfaz de administración (100.99.0.4 es solo un ejemplo).
+
+
+
+
+
+
+
+
+
Asegúrese de que el servidor SSH esté habilitado para que pueda iniciar sesión en el servidor más fácilmente después.
+
+
+
+
Puedes utilizar scp o sftp para acceder a los archivos de tu servidor LibreQoS y facilitar la modifición de archivos. Aquí se explica cómo acceder mediante scp o sftp usando una máquina Ubuntu o Windows.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/docs-es/v2.0/update-es.html b/_build/html/docs-es/v2.0/update-es.html
new file mode 100644
index 00000000..2b04c595
--- /dev/null
+++ b/_build/html/docs-es/v2.0/update-es.html
@@ -0,0 +1,168 @@
+
+
+
+
+
+
+
+
+ Actualización — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Si usas el puente XDP, el tráfico dejará de pasar por el puente mientras lqosd se reinicia (el puente XDP solo opera mientras lqosd está en ejecución).
There are two options for the bridge to pass data through your two interfaces:
+
+
Option A: Regular Linux Bridge (Recommended)
+
Option B: Bifrost XDP-Accelerated Bridge
+
+
The regular Linux bridge is recommended for most installations. The Linux Bridge continues to move data even if the lqosd service is in a failed state, making this a generally safer option in scenatios where a backup route is not in place. It works best with Nvidia/Mellanox NICs such as the ConnectX-5 series (which have superior bridge performance), and VM setups using virtualized NICs. The Bifrost XDP Bridge is recommended for 40G-100G Intel NICs with XDP support.
+
Below are the instructions to configure Netplan, whether using the Linux Bridge or Bifrost XDP bridge:
+
+
+
Option A: Netplan config for a regular Linux bridge (Recommended)
+
Ubuntu Server uses NetPlan, which uses .yaml files in /etc/netplan to determine interface settings.
+Here, we will add a .yaml specifically for LibreQoS - that way it is not overwritten when changes are made to the default .yaml file.
+
sudonano/etc/netplan/libreqos.yaml
+
+
+
Assuming your shaping interfaces are ens19 and ens20, here is what your file would look like:
Please be sure to replace ens19 and ens20 in the example above with the correct shaping interfaces. The order of the interfaces does not matter for this section.
+
+
By setting dhcp4:no and dhcp6:no, the shaping interfaces will be brought up as part of the normal boot cycle, despite not having IP addresses assigned.
Option B: Netplan config for the Bifrost XDP bridge
+
Ubuntu Server uses NetPlan, which uses .yaml files in /etc/netplan to determine interface settings.
+Here, we will add a .yaml specifically for LibreQoS - that way it is not overwritten when changes are made to the default .yaml file.
+
sudonano/etc/netplan/libreqos.yaml
+
+
+
Assuming your shaping interfaces are ens19 and ens20, here is what your file would look like:
Please be sure to replace ens19 and ens20 in the example above with the correct shaping interfaces. The order of the interfaces does not matter for this section.
+
+
By setting dhcp4:no and dhcp6:no, the shaping interfaces will be brought up as part of the normal boot cycle, despite not having IP addresses assigned.
If the status of one of the two services shows ‘failed’, examine why using journalctl, which shows the full status of the service. For example, if lqosd failed, you would run:
+
sudojournalctl-ulqosd-b
+
+
+
Press the End key on the keyboard to take you to the bottom of the log to see the latest updates to that log.
+
Lqosd will provide specific reasons it failed, such as an interface not being up, an interface lacking multi-queue, or other cocnerns.
WebUI (Node Manager) includes an urgent issue channel for high-priority events (for example, mapped-circuit limit enforcement and related operational warnings).
+
+
Urgent issues appear in the top navigation indicator.
+
They can be reviewed and acknowledged from the urgent issues modal.
+
Use this as an at-a-glance operational signal; confirm details in journalctl-ulqosd.
The configuration for each LibreQoS shaper box is stored in the file /etc/lqos.conf.
+
Edit the file to match your setup with
+
sudonano/etc/lqos.conf
+
+
+
In the [bridge] section, change to_internet and to_network to match your network interfaces.
+
+
to_internet="enp1s0f1"
+
to_network="enp1s0f2"
+
+
In the [bridge] section of the lqos.conf file, you can enable or disable the XDP Bridge with the setting use_xdp_bridge. The default value is false - because the default setup assumes a Linux Bridge. If you chose to use the XDP Bridge during that pre-requisites setup, please set use_xdp_bridge=true instead.
+
+
Set downlink_bandwidth_mbps and uplink_bandwidth_mbps to match the bandwidth in Mbps of your network’s upstream / WAN internet connection. The same can be done for generated_pn_download_mbps and generated_pn_upload_mbps.
+
to_internet would be the interface facing your edge router and the broader internet
+
to_network would be the interface facing your core router (or bridged internal network if your network is bridged)
+
+
Note: If you find that traffic is not being shaped when it should, please make sure to swap the interface order and restart lqosd as well as lqos_scheduler with sudosystemctlrestartlqosdlqos_scheduler.
+
After changing any part of /etc/lqos.conf it is highly recommended to always restart lqosd, using sudosystemctlrestartlqosd. This re-parses any new values in lqos.conf, making those new values accessible to both the Rust and Python sides of the code.
Network.json allows ISP operators to define a Hierarchical Network Topology, or Flat Network Topology.
+
If you plan to use the built-in UISP, Splynx, or Netzur integrations, you do not need to create a network.json file quite yet.
+If you plan to use the built-in UISP integration, it will create this automatically on its first run (assuming network.json is not already present).
+
If you will not be using an integration, you can manually define the network.json following the template file - network.example.json. Below is a table illustration of network.example.json.
+
Entire Network
Site_1
Site_2
AP_A
Site_3
Pop_1
AP_1
PoP_5
AP_7
AP_9
PoP_6
AP_11
+
For networks with no Parent Nodes (no strictly defined Access Points or Sites) edit the network.json to use a Flat Network Topology with
LibreQoS supports virtual nodes in network.json for organizational grouping and monitoring/aggregation in the WebUI/Insight. Virtual nodes are not included in the physical HTB shaping tree (they won’t create HTB classes and won’t enforce bandwidth limits).
+
To mark a node as virtual, set "virtual":true on that node.
During shaping, virtual nodes are removed and their children are promoted to the nearest non-virtual ancestor (see queuingStructure.json for the active physical plan).
+
ShapedDevices.csv can still use a virtual node as a ParentNode for display/grouping; LibreQoS will attach those circuits for shaping to the nearest non-virtual ancestor (top-level virtual nodes will be treated as unparented for shaping).
+
Avoid name collisions after promotion (two nodes with the same name ending up at the same level).
LibreQoS shapes individual devices by their IP addresses, which are grouped into “circuits”.
+
A circuit represents an ISP subscriber’s internet service, which may have just one associated IP (the subscriber’s router may be assigned a single /32 IPv4 for example) or it might have multiple IPs associated (maybe their router has a /29 assigned, or multiple /32s).
+
LibreQoS knows how to shape these devices, and what Node (AP, Site, etc) they are contained by, with the ShapedDevices.csv file.
If you are using one of our CRM integrations, this file will be automatically generated. If you are not using an integration, you can manually edit the file using either the WebUI or by directly editing the ShapedDevices.csv file through the CLI.
+
Directional SQM examples:
+
2794,"6 Littleton Drive, Ringgold, GA 30736",5,Device5,AP_11,,100.64.0.5,"fdd7:b724:0:500::/56",1,1,105,18,"",cake/fq_codel
+2795,"7 Example Ave",6,Device6,AP_11,,100.64.0.6,,1,1,105,18,"",/none
+
If you need to list multiple IPv4s in the IPv4 field, or multiple IPv6s in the IPv6 field, add a comma between them. If you are editing with a CSV editor (LibreOffice Calc, Excel), the CSV editor will automatically wrap these comma-seperated items with quotes for you. If you are editing the file manually with a utility like notepad or nano, please add quotes surrounding the comma-seperated entries.
+
2794,"6 Littleton Drive, Ringgold, GA 30736",5,Device5,AP_11,,100.64.0.5,"fdd7:b724:0:500::/56,fdd7:b724:0:600::/56",1,1,105,18,""
+
Modify the ShapedDevices.csv file using your preferred spreadsheet editor (LibreOffice Calc, Excel, etc), following the template file - ShapedDevices.example.csv
+
Circuit ID is required. The Circuit ID can be a number or string. This field must NOT include any number symbols (#). Every circuit requires a unique CircuitID - they cannot be reused. Here, circuit essentially refers to a customer’s service. If a customer has multiple locations on different parts of your network, use a unique CircuitID for each of those locations.
+
At least one IPv4 address or IPv6 address is required for each entry.
+
The Access Point or Site name should be set in the Parent Node field. Parent Node can be left blank for flat networks.
+
The ShapedDevices.csv file allows you to set minimum (guaranteed), and maximum allowed bandwidth per subscriber.
+
The Download Min and Upload Min for each Circuit must be 1 Mbps or greater. Generally, these should be set to 1 Mbps by default.
+
The Download Max and Upload Max for each Circuit must be 2 Mbps or greater. Generally, these correspond to the customer’s speed plan.
+
Recommendation: set the min bandwidth to 1/1 and max to 1.15X advertised plan rate:
+
+
This way, when an AP hits its ceiling, users have any remaining AP capacity fairly distributed between them.
+
By setting the max to 1.15X the speed plan, this makes it more likely that the subscriber will see a satisfactory speed test result, even if there is some small light traffic on their circuit running in the background - such as an HD video stream, software updates, etc.
+
This allows subscribers to utilize up to the maximum rate when AP has the capacity to allow that.
+
+
+
+
Note regarding SLAs: For customers with SLA contracts that guarantee them a minimum bandwidth, you can set their plan rate as the minimum bandwidth. That way when an AP approaches its ceiling, SLA customers will always see that rate available. Make sure that the combined minimum rates for circuits connected to a parent node do not exceed the rate of the parent node. If that happens, LibreQoS has a fail-safe that will reduce the minimums to 1/1 for all affected circuits.
+
Once your configuration is complete. You’re ready to run the application and start the systemd services
LibreQoS is placed inline at the edge of your network, usually between the network’s border router (NAT, firewall) and the core distribution router / switch.
If you use NAT/CG-NAT, please place LibreQoS inline prior to where NAT is applied, as LibreQoS needs to shape pre-NAT addresses (100.64.0.0/12) not public post-NAT IPs.
LibreQoS can parse MPLS traffic, however the traffic must follow the standard pattern:
+
(mplstags)(optionalvlantags)(ipheader)
+
+
+
If you use MPLS with a different tag pattern, you would ideally want to terminate MPLS traffic at the core distribution router / switch, before it reaches LibreQoS.
Option 1: Using Dynamic Routing (Strongly Recommended)
+
We recommend using dynamic routing protocols such as OSPF to create a high cost and low cost path between the edge router and core distribution router/switch. The low cost path should pass “through” the LibreQoS shaper bridge interfaces to allow LibreQoS to observe and shape traffic. For example, a low cost OSPF path may be set to a value of 1. The high-cost (backup) link would completely bypass LibreQoS, being set to a higher cost (perhaps 100 for OSPF) to ensure that traffic only takes that path when the LibreQoS shaper bridge is not operational.
When Rust finishes installing, it will tell you to execute a command to place the Rust build tools into your path. You need to either execute this command or logout and back in again.
+
Once that’s done, please run:
+
cd/opt/libreqos/src/
+./build_rust.sh
+
+
+
This will take a while the first time, but it puts everything in the right place.
You can now point a web browser at http://a.b.c.d:9123 (replace a.b.c.d with the management IP address of your shaping server) and enjoy a real-time view of your network.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/docs/v2.0/high-availability.html b/_build/html/docs/v2.0/high-availability.html
new file mode 100644
index 00000000..5cc7f3c0
--- /dev/null
+++ b/_build/html/docs/v2.0/high-availability.html
@@ -0,0 +1,242 @@
+
+
+
+
+
+
+
+
+ High Availability and Failure Domains — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
If you run BGP, use standard preference controls to make one path primary and one backup (for example local preference, MED, or AS path prepending based on your design). Keep policy deterministic and documented.
If you have more than one LibreQoS shaper box, you can select the shaper box you want to view using the Shaper Nodes dropdown box (located just below the search box).
By clicking the time selector (Last 24 Hours by default) you can set the time range for data display anywhere from 15 minutes to 28 days. You can also specify custom time periods (Now minus X minutes) or highly-specific detailed time periods.
The Shaper tab shows high-level stats for a particular LibreQoS shaper box.
+
+
Active Circuit Count: The number of active customer circuits observed - based on the subscriber’s traffic movement.
+
Throughput: Shaper box throughput
+
Shaper Packets: Packet-per-second rate of the Shaper box over time.
+
Shaper TCP Retransmits Percentage: The percentage of TCP packets observed that were retransmitted. Consider this a proxy for packet loss. This value should typically remain below 1 % across the network.
+
Shaper CAKE Activity: How active the CAKE shapers are on the network over time.
+
Shaper Round Trip Time: The Round Trip Time average of traffic moving across the network.
+
Shaper Round Trip Time Histogram: The Round Trip Time average of traffic moving across the network in histogram format.
+
Shaper CPU Utilization: The peak and average CPU utilization of the shaper box over time.
+
Shaper Memory Utilization: The RAM utilization of the shaper box over time.
This tab shows the health of Sites / Access Points / etc across the network in terms of their Round Trip Time, TCP Retransmits, and Capacity in each direction.
This view allows you to identify the general topology of the network from LibreQoS Insight’s perspective. If you hover over the bands between nodes, it will display the current throughput and TCP retransmits for that leg of the network.
Libby is LibreQoS Insight’s AI Chat Assistant. Libby can help with questions you may have about using LibreQoS or LibreQoS Insight. Libby leverages the official LibreQoS documentation to help you with any questions you may have. Libby can access both live and long-term data - both from synced LibreQoS shaper boxes and from Insight itself. Libby can reply to queries in most major languages with automatic translation.
+
You may find new ways to use Libby that we had not originally considered. Please feel welcome to share with us ways you have found Libby to help your workflow.
This view provides RTT, Retransmit, and Capacity heatmaps for every Access Point, OLT, and Site across your network in one view. This allows you to quickly spot trouble points on your network.
The Tree History is based on the Tree Overview display from the LibreQoS WebUI, and displays the sankey over time to help quickly identify network bottlenecks impacting performance.
LibreQoS Insight enables you to trigger AI-generated reports on specific subscriber circuits. These reports draw in from the customer’s last 7 days of network activity - including per-ASN performance characteristics, network topology context, and geographic context. The report identifies the User Profile, Key Findings, Critical Issues, Performance Trends, an Upgrade Recommendation, and suggestions for items to manually review.
Current builds can cache signed license grants locally so nodes can continue operating through temporary connectivity loss to Insight control services. Grant validity and expiration are enforced locally.
+
Operational notes:
+
+
Keep .keys/ persistent across reboots.
+
Treat .keys/ as sensitive local key material.
+
If grant or key state is invalid, lqosd logs will show license/grant errors.
enable_netzur toggles automatic imports by lqos_scheduler.
+
api_key is the Bearer token generated inside Netzur.
+
api_url must return JSON containing zones (mapped to sites) and customers (mapped to client circuits and devices).
+
timeout_secs overrides the default HTTP timeout (60 seconds) when the API is slow.
+
use_mikrotik_ipv6 enriches subscriber devices with IPv6 prefixes discovered via mikrotikDHCPRouterList.csv.
+
+
Run a manual import with:
+
python3integrationNetzur.py
+
+
+
The integration regenerates ShapedDevices.csv and, unless always_overwrite_network_json is disabled, updates network.json. Adjust the Integration → Common settings if you need to preserve an existing network map between Netzur syncs.
First, set the relevant parameters for Powercode (powercode_api_key, powercode_api_url, etc.) in /etc/lqos.conf.
+
To test the Powercode Integration, use
+
python3integrationPowercode.py
+
+
+
On the first successful run, it will create a ShapedDevices.csv file.
+You can modify the network.json file manually to reflect Site/AP bandwidth limits.
+ShapedDevices.csv will be overwritten every time the Powercode integration is run.
+You have the option to run integrationPowercode.py automatically on boot and every X minutes (set by the parameter queue_refresh_interval_mins), which is highly recommended. This can be enabled by setting enable_powercode=true in /etc/lqos.conf.
Most operators use this built-in integration path.
+If you use your own scripts as the source of truth for network.json and ShapedDevices.csv, start with Operating Modes and Source of Truth.
These integrations work by synchronizing with your CRM/NMS system to produce the two files LibreQoS requires for shaping - network.json and ShapedDevices.csv.
+
Important behavior when integrations are enabled:
+
+
ShapedDevices.csv is typically regenerated by integration sync jobs.
+
network.json overwrite behavior depends on your integration settings (for example always_overwrite_network_json).
+
Manual edits may be overwritten on the next refresh cycle.
⚠️ Breaking Change Notice: Prior to v1.5-RC-2, the default Splynx strategy was full. Starting with v1.5-RC-2, the default strategy is ap_only for improved CPU performance. If you require the previous behavior, explicitly set strategy="full" in your Splynx configuration section.
+
+
First, set the relevant parameters for Splynx (splynx_api_key, splynx_api_secret, etc.) in /etc/lqos.conf.
When using full topology strategy, you may encounter CPU performance bottlenecks where all traffic flows through a single root site, limiting throughput to what one CPU core can handle.
+
The promote_to_root feature solves this by promoting specific sites to root-level nodes, distributing traffic shaping across multiple CPU cores.
+
Configuration:
+
+
Navigate to Integration → Common in the WebUI
+
In the “Promote to Root Nodes” field, enter one site name per line:
The Splynx Integration uses Basic authentication. For using this type of authentication, please make sure you enable Unsecure access in your Splynx API key settings. Also the Splynx API key should be granted access to the necessary permissions.
+
+
+
Category
+
Name
+
Permission
+
+
+
+
Tariff Plans
+
Internet
+
View
+
+
FUP
+
Compiler
+
View
+
+
FUP
+
Policies
+
View
+
+
FUP
+
Capped Data
+
View
+
+
FUP
+
CAP Tariff
+
View
+
+
FUP
+
FUP Limits
+
View
+
+
Customers
+
Customer
+
View
+
+
Customers
+
Customers Online
+
View
+
+
Customers
+
Customer Internet services
+
View
+
+
Networking
+
Routers
+
View
+
+
Networking
+
Router contention
+
View
+
+
Networking
+
MikroTik
+
View
+
+
Networking
+
Monitoring
+
View
+
+
Networking
+
Network Sites
+
View
+
+
Networking
+
IPv4 Networks
+
View
+
+
Networking
+
IPv4 Networks IP
+
View
+
+
Networking
+
CPE
+
View
+
+
Networking
+
CPE AP
+
View
+
+
Networking
+
IPv6 Networks
+
View
+
+
Networking
+
IPv6 Networks IP (Addresses)
+
View
+
+
Administration
+
Locations
+
View
+
+
+
+
To test the Splynx Integration, use
+
python3integrationSplynx.py
+
+
+
On the first successful run, it will create a ShapedDevices.csv file and network.json.
+ShapedDevices.csv will be overwritten every time the Splynx integration is run.
+
To ensure the network.json is always overwritten with the newest version pulled in by the integration, please edit /etc/lqos.conf with the command sudonano/etc/lqos.conf.
+Edit the file to set the value of always_overwrite_network_json to true.
+Then, run sudosystemctlrestartlqosd.
+
You have the option to run integrationSplynx.py automatically on boot and every X minutes (set by the parameter queue_refresh_interval_mins), which is highly recommended. This can be enabled by setting enable_splynx=true under the [splynx_integration] section in /etc/lqos.conf.
+Once set, run sudosystemctlrestartlqos_scheduler.
You can also modify the the file integrationSplynxBandwidths.csv to override the default bandwidths for each Node (Site, AP).
+
A template is available in the /opt/libreqos/src folder. To utilize the template, copy the file integrationSplynxBandwidths.template.csv (removing the .template part of the filename) and set the appropriate information inside each file. For example, if you want to change the set bandwidth for a site, you would do:
enable_netzur toggles automatic imports by lqos_scheduler.
+
api_key is the Bearer token generated inside Netzur.
+
api_url must return JSON containing zones (mapped to sites) and customers (mapped to client circuits and devices).
+
timeout_secs overrides the default HTTP timeout (60 seconds) when the API is slow.
+
use_mikrotik_ipv6 enriches subscriber devices with IPv6 prefixes discovered via mikrotikDHCPRouterList.csv.
+
+
Run a manual import with:
+
python3integrationNetzur.py
+
+
+
The integration regenerates ShapedDevices.csv and, unless always_overwrite_network_json is disabled, updates network.json. Adjust the Integration → Common settings if you need to preserve an existing network map between Netzur syncs.
LibreQoS supports multiple topology strategies for UISP integration to balance CPU performance with network hierarchy needs:
+
+
+
Strategy
+
Description
+
CPU Impact
+
Use Case
+
+
+
+
flat
+
Only shapes subscribers by service plan speed
+
Lowest
+
Maximum performance, simple subscriber-only shaping
+
+
ap_only
+
Shapes by service plan and Access Point
+
Low
+
Good balance of performance and AP-level control
+
+
ap_site
+
Shapes by service plan, Access Point, and Site
+
Medium
+
Site-level aggregation with moderate complexity
+
+
full
+
Shapes entire network including backhauls, Sites, APs, and clients
+
Highest
+
Recommended for most deployments. Complete network hierarchy with backhaul awareness
+
+
+
+
Choosing the Right Strategy:
+
+
Use full for most deployments to get complete network topology awareness including backhaul links
+
Use ap_site if you need site-level control but don’t need backhaul shaping
+
Use ap_only for better performance when site aggregation isn’t needed
+
Use flat only when maximum performance is critical and you don’t need any hierarchy
+
+
Performance Note: When using full strategy with large networks, consider using the promote_to_root feature (see Promote to Root Nodes above) to distribute CPU load across multiple cores.
[uisp_integration]
+# Core Settings
+enable_uisp=true
+token="your-api-token-here"
+url="https://uisp.your_domain.com"
+site="Root_Site_Name"# Root site for topology perspective
+
+# Topology Strategy (see table above)
+strategy="full"# Recommended for most deployments
+
+# Suspension Handling (see table above)
+suspended_strategy="none"
+
+# Capacity Adjustments
+# UISP's reported AP capacities can be optimistic
+airmax_capacity=0.65# Use 65% of reported AirMax capacity
+ltu_capacity=0.95# Use 95% of reported LTU capacity
+
+# Site Management
+exclude_sites=[]# Sites to exclude, e.g., ["Test_Site", "Lab_Site"]
+use_ptmp_as_parent=true# For sites branched off PtMP Access Points
+
+# Bandwidth Adjustments
+bandwidth_overhead_factor=1.15# Give customers 15% above plan speed
+commit_bandwidth_multiplier=0.98# Set minimum to 98% of maximum (CIR)
+
+# Advanced Options
+ipv6_with_mikrotik=false# Enable if using DHCPv6 with MikroTik
+always_overwrite_network_json=false# Set true to rebuild topology each run
+exception_cpes=[]# CPE exceptions in ["cpe:parent"] format
+squash_sites=[]# Optional: sites to squash
+enable_squashing=false# Optional: enable AP/single-entry squashing logic
+do_not_squash_sites=[]# Optional: never squash these sites
+ignore_calculated_capacity=false# Optional: keep configured capacities even if calculated differs
+insecure_ssl=false# Optional: ignore UISP TLS certificate validation
+
On the first successful run, it will create a network.json and ShapedDevices.csv file.
+If a network.json file exists, it will not be overwritten, unless you set always_overwrite_network_json=true.
+
ShapedDevices.csv will be overwritten every time the UISP integration is run.
+
To ensure the network.json is always overwritten with the newest version pulled in by the integration, please edit /etc/lqos.conf with the command sudonano/etc/lqos.conf.
+Edit the file to set the value of always_overwrite_network_json to true.
+Then, run sudosystemctlrestartlqosd.
+
You have the option to run integrationUISP.py automatically on boot and every X minutes (set by the parameter queue_refresh_interval_mins), which is highly recommended. This can be enabled by setting enable_uisp=true in /etc/lqos.conf. Once set, run sudosystemctlrestartlqos_scheduler.
You can also modify the the following files to more accurately reflect your network:
+
+
integrationUISPbandwidths.csv
+
integrationUISProutes.csv
+
+
Each of the files above have templates available in the /opt/libreqos/src folder. If you don’t find them there, you can navigate here. To utilize the template, copy the file (removing the .template part of the filename) and set the appropriate information inside each file.
+For example, if you want to change the set bandwidth for a site, you would do:
The default cost between nodes is typically 10. The integration creates a dot graph file /opt/libreqos/src/graph.dot which can be rendered using Graphviz. This renders a map with the associated costs of all links.
+
+
Say you have Site 1, Site 2, and Site 3.
+A backup path exists between Site 1 and Site 3, but is not the preferred path.
+Your preference is Site 1 > Site 2 > Site 3, but the integration by default connects Site 1 > Site 3 directly.
+
To fix this, add a cost above the default for the path between Site 1 and Site 3.
+
Site1,Site3,100
+Site3,Site1,100
+
+
+
With this, data will flow Site 1 > Site 2 > Site 3.
+
To make the change, perform a reload of the integration with sudosystemctlrestartlqos_scheduler.
If the section is missing, you can add it by copying the section above.
+Set the appropriate values for wispgate_api_token and wispgate_api_url, then save the file.
+
To test the WISPGate Integration, use
+
python3integrationWISPGate.py
+
+
+
On the first successful run, it will create a ShapedDevices.csv file and network.json.
+ShapedDevices.csv will be overwritten every time the WISPGate integration is run.
+
To ensure the network.json is always overwritten with the newest version pulled in by the integration, please edit /etc/lqos.conf with the command sudonano/etc/lqos.conf.
+Edit the file to set the value of always_overwrite_network_json to true.
+Then, run sudosystemctlrestartlqosd.
+
You have the option to run integrationWISPGate.py automatically on boot and every X minutes (set by the parameter queue_refresh_interval_mins), which is highly recommended. This can be enabled by setting enable_wispgate=true in /etc/lqos.conf.
+Once set, run sudosystemctlrestartlqos_scheduler.
First, set the relevant parameters for Powercode (powercode_api_key, powercode_api_url, etc.) in /etc/lqos.conf.
+
To test the Powercode Integration, use
+
python3integrationPowercode.py
+
+
+
On the first successful run, it will create a ShapedDevices.csv file.
+You can modify the network.json file manually to reflect Site/AP bandwidth limits.
+ShapedDevices.csv will be overwritten every time the Powercode integration is run.
+You have the option to run integrationPowercode.py automatically on boot and every X minutes (set by the parameter queue_refresh_interval_mins), which is highly recommended. This can be enabled by setting enable_powercode=true in /etc/lqos.conf.
First, set the relevant parameters for Sonar (sonar_api_key, sonar_api_url, etc.) in /etc/lqos.conf.
+
To test the Sonar Integration, use
+
python3integrationSonar.py
+
+
+
On the first successful run, it will create a ShapedDevices.csv file.
+If a network.json file exists, it will not be overwritten, unless you set always_overwrite_network_json=true.
+You can modify the network.json file to more accurately reflect bandwidth limits.
+ShapedDevices.csv will be overwritten every time the Sonar integration is run.
+You have the option to run integrationSonar.py automatically on boot and every X minutes (set by the parameter queue_refresh_interval_mins), which is highly recommended. This can be enabled by setting enable_sonar=true in /etc/lqos.conf.
Jesync UI Tool Dashboard is a modern, web-based control panel designed to make managing LibreQoS and its integration files easier, faster, and more user-friendly.
This script automates the synchronization of MikroTik PPP secrets (e.g., PPPoE users) and active hotspot users with a LibreQoS-compatible CSV file (ShapedDevices.csv). It continuously monitors the MikroTik router for changes to PPP secrets and active hotspot users, such as additions, updates, or deletions, and updates the CSV file accordingly. The script also calculates rate limits (download/upload speeds) based on the assigned PPP profile and ensures the CSV file is always up-to-date.
+
The script is designed to run as a background service using systemd, ensuring it starts automatically on boot and restarts in case of failures.
First, set the relevant parameters for Sonar (sonar_api_key, sonar_api_url, etc.) in /etc/lqos.conf.
+
To test the Sonar Integration, use
+
python3integrationSonar.py
+
+
+
On the first successful run, it will create a ShapedDevices.csv file.
+If a network.json file exists, it will not be overwritten, unless you set always_overwrite_network_json=true.
+You can modify the network.json file to more accurately reflect bandwidth limits.
+ShapedDevices.csv will be overwritten every time the Sonar integration is run.
+You have the option to run integrationSonar.py automatically on boot and every X minutes (set by the parameter queue_refresh_interval_mins), which is highly recommended. This can be enabled by setting enable_sonar=true in /etc/lqos.conf.
⚠️ Breaking Change Notice: Prior to v1.5-RC-2, the default Splynx strategy was full. Starting with v1.5-RC-2, the default strategy is ap_only for improved CPU performance. If you require the previous behavior, explicitly set strategy="full" in your Splynx configuration section.
+
+
First, set the relevant parameters for Splynx (splynx_api_key, splynx_api_secret, etc.) in /etc/lqos.conf.
When using full topology strategy, you may encounter CPU performance bottlenecks where all traffic flows through a single root site, limiting throughput to what one CPU core can handle.
+
The promote_to_root feature solves this by promoting specific sites to root-level nodes, distributing traffic shaping across multiple CPU cores.
+
Configuration:
+
+
Navigate to Integration → Common in the WebUI
+
In the “Promote to Root Nodes” field, enter one site name per line:
The Splynx Integration uses Basic authentication. For using this type of authentication, please make sure you enable Unsecure access in your Splynx API key settings. Also the Splynx API key should be granted access to the necessary permissions.
+
+
+
Category
+
Name
+
Permission
+
+
+
+
Tariff Plans
+
Internet
+
View
+
+
FUP
+
Compiler
+
View
+
+
FUP
+
Policies
+
View
+
+
FUP
+
Capped Data
+
View
+
+
FUP
+
CAP Tariff
+
View
+
+
FUP
+
FUP Limits
+
View
+
+
Customers
+
Customer
+
View
+
+
Customers
+
Customers Online
+
View
+
+
Customers
+
Customer Internet services
+
View
+
+
Networking
+
Routers
+
View
+
+
Networking
+
Router contention
+
View
+
+
Networking
+
MikroTik
+
View
+
+
Networking
+
Monitoring
+
View
+
+
Networking
+
Network Sites
+
View
+
+
Networking
+
IPv4 Networks
+
View
+
+
Networking
+
IPv4 Networks IP
+
View
+
+
Networking
+
CPE
+
View
+
+
Networking
+
CPE AP
+
View
+
+
Networking
+
IPv6 Networks
+
View
+
+
Networking
+
IPv6 Networks IP (Addresses)
+
View
+
+
Administration
+
Locations
+
View
+
+
+
+
To test the Splynx Integration, use
+
python3integrationSplynx.py
+
+
+
On the first successful run, it will create a ShapedDevices.csv file and network.json.
+ShapedDevices.csv will be overwritten every time the Splynx integration is run.
+
To ensure the network.json is always overwritten with the newest version pulled in by the integration, please edit /etc/lqos.conf with the command sudonano/etc/lqos.conf.
+Edit the file to set the value of always_overwrite_network_json to true.
+Then, run sudosystemctlrestartlqosd.
+
You have the option to run integrationSplynx.py automatically on boot and every X minutes (set by the parameter queue_refresh_interval_mins), which is highly recommended. This can be enabled by setting enable_splynx=true under the [splynx_integration] section in /etc/lqos.conf.
+Once set, run sudosystemctlrestartlqos_scheduler.
You can also modify the the file integrationSplynxBandwidths.csv to override the default bandwidths for each Node (Site, AP).
+
A template is available in the /opt/libreqos/src folder. To utilize the template, copy the file integrationSplynxBandwidths.template.csv (removing the .template part of the filename) and set the appropriate information inside each file. For example, if you want to change the set bandwidth for a site, you would do:
[uisp_integration]
+# Core Settings
+enable_uisp=true
+token="your-api-token-here"
+url="https://uisp.your_domain.com"
+site="Root_Site_Name"# Root site for topology perspective
+
+# Topology Strategy (see table above)
+strategy="full"# Recommended for most deployments
+
+# Suspension Handling (see table above)
+suspended_strategy="none"
+
+# Capacity Adjustments
+# UISP's reported AP capacities can be optimistic
+airmax_capacity=0.65# Use 65% of reported AirMax capacity
+ltu_capacity=0.95# Use 95% of reported LTU capacity
+
+# Site Management
+exclude_sites=[]# Sites to exclude, e.g., ["Test_Site", "Lab_Site"]
+use_ptmp_as_parent=true# For sites branched off PtMP Access Points
+
+# Bandwidth Adjustments
+bandwidth_overhead_factor=1.15# Give customers 15% above plan speed
+commit_bandwidth_multiplier=0.98# Set minimum to 98% of maximum (CIR)
+
+# Advanced Options
+ipv6_with_mikrotik=false# Enable if using DHCPv6 with MikroTik
+always_overwrite_network_json=false# Set true to rebuild topology each run
+exception_cpes=[]# CPE exceptions in ["cpe:parent"] format
+squash_sites=[]# Optional: sites to squash
+enable_squashing=false# Optional: enable AP/single-entry squashing logic
+do_not_squash_sites=[]# Optional: never squash these sites
+ignore_calculated_capacity=false# Optional: keep configured capacities even if calculated differs
+insecure_ssl=false# Optional: ignore UISP TLS certificate validation
+
On the first successful run, it will create a network.json and ShapedDevices.csv file.
+If a network.json file exists, it will not be overwritten, unless you set always_overwrite_network_json=true.
+
ShapedDevices.csv will be overwritten every time the UISP integration is run.
+
To ensure the network.json is always overwritten with the newest version pulled in by the integration, please edit /etc/lqos.conf with the command sudonano/etc/lqos.conf.
+Edit the file to set the value of always_overwrite_network_json to true.
+Then, run sudosystemctlrestartlqosd.
+
You have the option to run integrationUISP.py automatically on boot and every X minutes (set by the parameter queue_refresh_interval_mins), which is highly recommended. This can be enabled by setting enable_uisp=true in /etc/lqos.conf. Once set, run sudosystemctlrestartlqos_scheduler.
You can also modify the the following files to more accurately reflect your network:
+
+
integrationUISPbandwidths.csv
+
integrationUISProutes.csv
+
+
Each of the files above have templates available in the /opt/libreqos/src folder. If you don’t find them there, you can navigate here. To utilize the template, copy the file (removing the .template part of the filename) and set the appropriate information inside each file.
+For example, if you want to change the set bandwidth for a site, you would do:
The default cost between nodes is typically 10. The integration creates a dot graph file /opt/libreqos/src/graph.dot which can be rendered using Graphviz. This renders a map with the associated costs of all links.
+
+
Say you have Site 1, Site 2, and Site 3.
+A backup path exists between Site 1 and Site 3, but is not the preferred path.
+Your preference is Site 1 > Site 2 > Site 3, but the integration by default connects Site 1 > Site 3 directly.
+
To fix this, add a cost above the default for the path between Site 1 and Site 3.
+
Site1,Site3,100
+Site3,Site1,100
+
+
+
With this, data will flow Site 1 > Site 2 > Site 3.
+
To make the change, perform a reload of the integration with sudosystemctlrestartlqos_scheduler.
If the section is missing, you can add it by copying the section above.
+Set the appropriate values for wispgate_api_token and wispgate_api_url, then save the file.
+
To test the WISPGate Integration, use
+
python3integrationWISPGate.py
+
+
+
On the first successful run, it will create a ShapedDevices.csv file and network.json.
+ShapedDevices.csv will be overwritten every time the WISPGate integration is run.
+
To ensure the network.json is always overwritten with the newest version pulled in by the integration, please edit /etc/lqos.conf with the command sudonano/etc/lqos.conf.
+Edit the file to set the value of always_overwrite_network_json to true.
+Then, run sudosystemctlrestartlqosd.
+
You have the option to run integrationWISPGate.py automatically on boot and every X minutes (set by the parameter queue_refresh_interval_mins), which is highly recommended. This can be enabled by setting enable_wispgate=true in /etc/lqos.conf.
+Once set, run sudosystemctlrestartlqos_scheduler.
Use this page to choose and configure supported CRM/NMS integrations. Use per-integration pages for specific setup details.
+
Most operators use built-in integrations. If you use your own scripts as the source of truth for network.json and ShapedDevices.csv, start with Operating Modes and Source of Truth.
+
+ flowchart LR
+ A[CRM/NMS] --> B[LibreQoS Integration Job]
+ B --> C[ShapedDevices.csv]
+ B --> D[network.json]
+ C --> E[lqos_scheduler]
+ D --> E
+ E --> F[Shaping Updates]
+ E --> G[WebUI Status / Urgent Issues]
+
Use this page to choose and enforce your source-of-truth policy (built-in integrations vs custom source-of-truth) before production changes.
+
+ flowchart TD
+ A[Choose Source of Truth] --> B{Using built-in CRM/NMS integration?}
+ B -->|Yes| C[Built-in Integrations Mode]
+ B -->|No| D{Generating files from your own scripts/systems?}
+ D -->|Yes| E[Custom Source-of-Truth Mode]
+ D -->|No| F[Manual Files Mode]
+ C --> G[Integration sync jobs own file refresh]
+ E --> H[External script pipeline owns persistence]
+ F --> I[Direct file maintenance; best for small networks]
+
LibreQoS supports two first-class operating modes.
+
+
+
Built-in Integrations (Recommended for Most Operators)
+
In this mode, your CRM/NMS is the source of truth and LibreQoS integration jobs produce shaping inputs.
+
Key behavior:
+
+
ShapedDevices.csv is regenerated by integration sync cycles.
+
network.json overwrite behavior depends on integration settings (for example always_overwrite_network_json).
+
Direct manual edits may be overwritten on the next scheduler refresh.
Disable hyperthreading on the BIOS/UEFI of your host system. Hyperthreaading is also known as Simultaneous Multi Threading (SMT) on AMD systems. Disabling this is very important for optimal performance of the XDP cpumap filtering and, in turn, throughput and latency.
+
+
Boot, pressing the appropriate key to enter the BIOS settings
+
For AMD systems, you will have to navigate the settings to find the “SMT Control” setting. Usually it is under something like Advanced->AMDCBS->CPUCommonOptions->ThreadEnablement->SMTControl Once you find it, switch to “Disabled” or “Off”
+
For Intel systems, you will also have to navigate the settings to find the “hyperthrading” toggle option. On HP servers it’s under SystemConfiguration>BIOS/PlatformConfiguration(RBSU)>ProcessorOptions>Intel(R)HyperthreadingOptions.
SR-IOV can disable XDP native (driver mode) on Physical Functions (PFs), forcing XDP Generic (SKB) and reducing performance and stability for LibreQoS. Disable SR-IOV in BIOS/UEFI for NICs used by LibreQoS. If per-slot/per-port options exist, set them to Disabled.
For Proxmox VMs, NIC passthrough is required to achieve throughput above 10 Gbps (XDP vs generic XDP).
+
LibreQoS requires 2 or more RX/TX queues, so when using Proxmox, please be sure to enable Multiqueue for the shaping interfaces assigned to the VM. Multiqueue should be set equal to the number of vCPU cores assigned to the VM.
If your LibreQoS system is running inside Hyper-V and you’ve bridged two vNICs (eth1, eth2) — Hyper-V will block traffic from the bridge because the bridge generates frames with different MACs than the vNIC’s assigned MAC. To fix this on a Windows host:
Use this page to choose the correct deployment path quickly, then execute only the steps for that path.
+
+ flowchart TD
+ A[Start Here: Quickstart] --> B{Choose Path}
+ B --> C[Testbed / Lab]
+ B --> D[Supported Integration]
+ B --> E[Custom Script Integration]
+ B --> F[Manual Files <100 subscribers]
+ C --> G[Configure + Validate in WebUI]
+ D --> G
+ E --> G
+ F --> G
+ G --> H[Troubleshoot / Optimize / Scale]
+
Choose a CPU with high single-thread performance within your budget. Queuing is CPU-intensive, and requires high single-thread performance.
+
+
Single-thread CPU performance determines the maximum capacity of a single HTB (CPU core). This, in turn, affects the maximum capacity of any top-level node in the network hierarchy (e.g., top-level sites in your network). This also impacts the maximum speed plan you can offer customers within safe margins.
+
+
+
Single-Thread Score
+
Top-Level Node Max
+
Customer Plan Max
+
+
+
+
1000
+
1 Gbps
+
100 Mbps
+
+
1500
+
2 Gbps
+
500 Mbps
+
+
2000
+
3 Gbps
+
1 Gbps
+
+
3000
+
4 Gbps
+
2 Gbps
+
+
4000
+
5 Gbps
+
3 Gbps
+
+
+
+
Below is a table of approximate aggregate capacity, assuming a CPU with a single thread performance rating of 1000, 2000, 3000, or 4000:
As with any machine running LibreQoS, please be sure to disable hyperthreading. Specific to the MS-01, please consider replacing the thermal paste to lower CPU temps by about 20 degrees celcius (Note: this may void the warranty).
Another cost-effective solution is to procure a used server from a reputable vendor, such as TheServerStore.
+Such vendors often stock servers capable of 10 Gbps throughput, for around $500 USD.
One management network interface completely separate from the traffic shaping interfaces. Usually this would be the Ethernet interface built in to the motherboard.
+
A Dedicated Network Interface Card for Two Shaping Interfaces
+
+
+
⚠️ Bonded Interfaces: LibreQoS does not support the use of bonded interfaces. This is a limitation of XDP.
+
+
Officially supported Network Interface Cards for the two shaping interfaces are listed below:
(*) Intel often vendor-locks SFP+ module compatibility. Check module compatibility before buying. Mellanox does not have this problem.
+
We will ONLY provide support for systems using a NIC listed above. Some other NICs may work, but will not be officially supported by LibreQoS. If you want to test the compatability of another card, please be aware of these fundamental NIC requirements:
LibreQoS can be run as a VM, although this comes at a performance penalty of 30%. For VMs, NIC passthrough is required to achieve throughput above 10 Gbps (XDP vs generic XDP).
+LibreQoS requires 2 or more RX/TX queues, so when using a virtualization platform such as Proxmox, be sure to enable Multiqueue for the shaping interfaces assigned to the VM. Multiqueue should be set equal to the number of vCPU cores assigned to the VM.
+
+
+
Throughput
+
vCPU*
+
RAM
+
Disk
+
+
+
+
1 Gbps
+
2
+
8 GB
+
50 GB
+
+
10 Gbps
+
8
+
32 GB
+
50 GB
+
+
+
+
+
Assumes vCPU performance equal to a single core of the Intel Xeon E-2456 with hyper-threading disabled.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/docs/v2.0/scale-topology.html b/_build/html/docs/v2.0/scale-topology.html
new file mode 100644
index 00000000..d31c1eb8
--- /dev/null
+++ b/_build/html/docs/v2.0/scale-topology.html
@@ -0,0 +1,250 @@
+
+
+
+
+
+
+
+
+ Scale Planning and Topology Design — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
StormGuard is LibreQoS’ adaptive queue-adjustment subsystem for congestion and quality events.
+
+
Important Scope Warning
+StormGuard is intended for specific use cases, such as controlling congestion on variable-bandwidth WAN links (for example maritime networks), or a small number of access points with highly variable capacity.
+It is not intended to manage dozens or hundreds of nodes at the same time.
The WebUI is controlled by the lqosd service. Usually, when the WebUI doesn’t start, it is related to lqosd being in a failed state.
+Check to see if the lqosd service is running:
+
sudosystemctlstatuslqosd
+
+
+
If the status is ‘failed’, examine why using journalctl, which shows the full status of the service:
+
journalctl-ulqosd--since"10 minutes ago"
+
+
+
Press the End key on the keyboard to take you to the bottom of the log to see the latest updates to that log.
+
Lqosd will provide specific reasons it failed, such as an interface not being up, an interface lacking multi-queue, or other cocnerns.
In /etc/lqos.conf, ensure that to_internet and to_network are set correctly. If not, simply swap the interfaces between those and restart lqosd and the scheduler.
+
sudosystemctlrestartlqosdlqos_scheduler
+
+
+
Make sure your services are running properly
+
sudosystemctlstatuslqosdlqos_scheduler
+
+
+
The service lqos_scheduler is dependent on the lqosd service being in a healthy, running state.
+
+
+
On-a-stick shaping looks wrong or one direction is weak
+
On-a-stick mode depends on queue splitting per direction. If TX queue discovery is wrong or override_available_queues is mis-set, directional mapping can be degraded.
If sudosystemctlstatuslqosdlqos_scheduler reveals that the lqos_scheduler service has issues, you can export a comprehensive log of the errors to a file:
+
sudojournalctl-ulqos_scheduler--since"1 day ago"--no-pager>lqos_sched_log.txt
+
+
+
This exports a log file to lqos_sched_log.txt. You can review this file to see what caused the scheduler to error out.
This tends to show up when the MQ qdisc cannot be added correctly to the NIC interface. This would suggest the NIC has insufficient RX/TX queues. Please make sure you are using the recommended NICs.
The console output from running LibreQoS.py directly provides more specific errors regarding issues with ShapedDevices.csv and network.json
+Once you have identified the error and fixed ShapedDevices.csv and/or Network.json, please then run
+
sudosystemctlstartlqos_scheduler
+
+
+
Flow Map / Tree Overview / ASN Explorer appears blank
+
Some views require enough recent data to render meaningfully. If pages look empty:
+
+
Confirm lqosd is healthy.
+
Wait for traffic/data to accumulate.
+
Reload the page after 1-2 minutes.
+
Check logs for websocket or ticker warnings:
+
+
journalctl-ulqosd--since"10 minutes ago"
+
+
+
If still blank under normal traffic, collect recent logs and open an issue.
If LibreQoS.py fails with an error like Virtualnodepromotioncollision:'AP_A'alreadyexistsatthislevel., you have a "virtual":true node whose children get promoted into a parent level where a node with the same name already exists.
+
Rename one of the colliding nodes (names must be unique among siblings after virtual-node promotion), or restructure the hierarchy so promoted children won’t collide.
LibreQoS is enforcing a mapped-circuit cap. In current builds, default behavior without active Insight licensing enforces a finite mapped-circuit limit.
+
Recommended checks:
+
+
Confirm Insight/license status in the UI.
+
Review lqosd logs for requested/allowed/dropped counts.
You can download Ubuntu Server 24.04 LTS from here.
+At this time, only Ubuntu Server 24.04 is supported. Please be sure not to use other versions.
+
+
Boot Ubuntu Server from USB.
+
Follow the steps below to install Ubuntu Server.
+
+
+
+
+
For the network interfaces, disable the shaping interfaces entirely. Then, set a static IP address on the management interface (100.99.0.4 is just an example).
+
+
+
+
+
+
+
+
+
Ensure SSH server is enabled so you can more easily log into the server later.
+
+
+
+
You can use scp or sftp to access files from your LibreQoS server for easier file editing. Here’s how to access via scp or sftp using an Ubuntu or Windows machine.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/docs/v2.0/update.html b/_build/html/docs/v2.0/update.html
new file mode 100644
index 00000000..dc6a620a
--- /dev/null
+++ b/_build/html/docs/v2.0/update.html
@@ -0,0 +1,192 @@
+
+
+
+
+
+
+
+
+ Upgrading — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
rust/remove_pinned_maps.sh removes pinned maps used by the eBPF/XDP pipeline so newer map schemas can load cleanly after upgrades.
+
Recent versions include additional map cleanup (including ip_mapping_epoch). If this cleanup is skipped after a schema-changing upgrade, you may see stale behavior or mapping inconsistencies.
+
If you use Git installs, keep this order:
+
+
build/update binaries
+
stop/restart services as needed
+
run sudorust/remove_pinned_maps.sh
+
restart lqosd and lqos_scheduler
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/genindex.html b/_build/html/genindex.html
new file mode 100644
index 00000000..47508578
--- /dev/null
+++ b/_build/html/genindex.html
@@ -0,0 +1,570 @@
+
+
+
+
+
+
+
+ Index — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index
+
+
+
+
+
+
+
+
+
+
Index
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/index.html b/_build/html/index.html
new file mode 100644
index 00000000..82b53959
--- /dev/null
+++ b/_build/html/index.html
@@ -0,0 +1,179 @@
+
+
+
+
+
+
+
+
+ Welcome to the LibreQoS documentation — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
This process cannot all be done in LibreQoS - all of the email sending, license generation, data
+storage (etc.) are handled by Insight (lts2). Insight is in a different repository.
+
The lts_trial.html page needs to display the teaser data with the following requirements:
+
+
Use Bootstrap5 and FontAwesome (free) icons.
+
We’re using jQuery for REST calls.
+
Use CSS that fits with other LibreQoS pages, including working with Day/Night modes.
+
Use the lts_trial.js file to handle the JavaScript logic. Remember the “cache busting” technique
+to ensure the latest version is loaded. Check other HTML files for examples.
+
+
The teaser itself should be modular, so we can add image/text for feature content to highlight. IDEALLY, you should
+define a schema for the teaser data to be loaded dynamically from a POST to the Insight server. The schema should be
+clearly documented. Each teaser should have a title, description and an image URL. The design should be responsive
+(with Bootstrap) and work well on mobile devices as well as desktops.
+
Please also come up with a 3-item placeholder teaser that we can use for testing purposes. Use comments
+to make it clear where we will load the teaser data from the Insight server instead of using static test data.
+
The page itself should:
+
+
Be a fragment so that the template.rs system can load it.
+
Display the teaser as a “jumbotron” or similar style panel.
+
Every teaser page should have two buttons:
+
+
“I have a license key” - which will show the license key input form.
+
“I want to try Insight for free” - which will show the customer info capture form.
+
Both buttons should be styled with Bootstrap and use FontAwesome icons.
+
+
+
+
For bonus points, use the existing dashboard API to find out how many active circuits the user has, and
+display that information - at a cost of $0.30 per circuit per month, this is a great deal!
+
The “configure LibreQOS” step should be left as a placeholder, invoking a Rust function
+in lqosd that will configure lqos.conf and restart the service.
+This will be implemented later.
Returns status code 200 whether it succeeded or not, and sends email if the email is valid and
+has a license key associated with it (to avoid fishing trips!)
Please validate all fields on the client side. At an absolute minimum, we HAVE to have their
+name, email, and location information (address, city, state, zip, country). We should also
+make sure we don’t sign-up users from countries embargoed by the US government, such as Russia, Iran, North Korea, etc.
+etc.
+
Country lists MUST be compatible with Paddle Billing (which Insight server users). The full
+list is here: https://developer.paddle.com/concepts/sell/supported-countries-locales
+
We absolutely mustn’t change the configuration of LibreQoS until we know everything worked.
help.html is a decent Bootstrap5 example we use, as is the main dashboard page. Mostly, we
+want it to be clear, modern, accessible and responsive. Use existing pages for inspiration,
+but please feel free to innovate and make it look great!
The active circuit count should be located by counting circuits in the ShapedDevices.csv file. There’s a ssection of
+of the lqos_config crate that can be used to read this file and count the active circuits. We may have
+to add a new API endpoint to the lqosd service to expose this information, but it should be straightforward.
+
Make this a lower priority, towards the end of this process, as it is not critical to the sign-up flow.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/src/INSIGHT_SIGNUP_SERVER_PLAN.html b/_build/html/src/INSIGHT_SIGNUP_SERVER_PLAN.html
new file mode 100644
index 00000000..3b75ce98
--- /dev/null
+++ b/_build/html/src/INSIGHT_SIGNUP_SERVER_PLAN.html
@@ -0,0 +1,544 @@
+
+
+
+
+
+
+
+
+ Insight Signup Server Implementation Plan — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
This document describes the server-side implementation for the LibreQoS Insight signup API endpoints. The server will be implemented using FastAPI (Python web framework) and will integrate with existing databases.
+
The overall process (including from the LibreQoS client side) is as follows:
The teasers should be stored as a JSON file that can be loaded dynamically. The schema is further down in this
+document. The docker compose setup should explose this as a directory, so that the server can read the file -
+and we can edit it as needed without redeploying the server. There’s no need to complicate this with a database.
“Teaser” entries can include a static image URL. This should point to /signup-api/image?id=teaser-id and log
+that the image was loaded for analytics purposes. The server should serve these images from a static directory.
+The images should be exposed as a directory via the Docker Compose setup, so they can be easily updated without redeploying the server.
There are several items that send email. The mailer_svc NATS service will handle sending the emails. It has
+a handlebars templating system and allows for complex HTML templates as well as plain text. We’ll need to
+expand our plan to include all of the appropriate email templates. A bonus would be to store these in a docker-compose
+exposed directory, so that we can edit them without redeploying the server.
Country must be in allowed list (exclude embargoed countries)
+
Email must be unique (one license per email)
+
Generate unique license key
+
Create customer record in database
+
Send welcome email with license key and portal credentials
+
Create trial subscription (30 days)
+
Log signup for analytics
+
+
Welcome Email Template:
+
Subject: Welcome to LibreQoS Insight - Your Trial Has Started!
+
+Hello [Name],
+
+Welcome to LibreQoS Insight! Your 30-day trial has been activated.
+
+Your License Key: XXXX-XXXX-XXXX-XXXX
+
+Portal Access:
+URL: https://insight.libreqos.com/portal
+Email: [email]
+Password: [temporary password]
+
+Your trial includes:
+- Real-time network analytics
+- Advanced reporting suite
+- Proactive alerts
+- Full API access
+
+Getting Started:
+1. Your LibreQoS system should now be connected to Insight
+2. Log into the portal to view your network analytics
+3. Check out our documentation at https://docs.libreqos.com/insight
+
+Questions? Reply to this email or visit our support portal.
+
+Best regards,
+LibreQoS Team
+
Existing database tables are found in the db_setup project, and we’d like to use them. We can make
+modifications to the schema if we need to, but we should try to avoid that if possible.
If you need to create an integration for your network, we’ve tried to give you the tools you need. We currently ship integrations for UISP and Splynx. We’d love to include more.
LibreQoS enforces customer bandwidth limits, and applies CAKE-based optimizations at several levels:
+
+
Per-user Cake flows are created. These require the maximum bandwidth permitted per customer.
+
+
Customers can have more than one device that share a pool of bandwidth. Customers are grouped into “circuits”
+
+
+
Optional Access points can have a speed limit/queue, applied to all customers associated with the access point.
+
Optional Sites can contain access points, and apply a speed limit/queue to all access points (and associated circuits).
+
Optional Sites can be nested beneath other sites and access point, providing for a queue hierarchy that represents physical limitations of backhaul connections.
+
+
Additionally, you might grow to have more than one shaper - and need to express your network topology from the perspective of different parts of your network. (For example, if Site A and Site B both have Internet connections - you want to generate an efficient topology for both sites. It’s helpful if you can derive this from the same overall topology)
+
LibreQoS’s network modeling accomplishes this by modeling your network as a graph: a series of interconnected nodes, each featuring a “parent”. Any “node” (entry) in the graph can be turned into a “root” node, allowing you to generate the network.json and ShapedDevices.csv files required to manage your customers from the perspective of that root node.
The simplest form of integration produces a “flat” network. This is the highest performance model in terms of raw throughput, but lacks the ability to provide shaping at the access point or site level: every customer site is parented directly off the root.
+
+
For an integration, it’s recommended that you fetch the customer/device data from your management system rather than type them all in Python.
+
+
A flat integration is relatively simple. Start by importing the common API:
Then create an empty network graph (it will grow to represent your network):
+
net=NetworkGraph()
+
+
+
Once you have your NetworkGraph object, you start adding customers and devices. Customers may have any number of devices. You can add a single customer with one device as follows:
+
# Add the customer
+customer=NetworkNode(
+ id="Unique Customer ID",
+ displayName="The Doe Family",
+ type=NodeType.client,
+ download=100,# Download is in Mbit/second
+ upload=20,# Upload is in Mbit/second
+ address="1 My Road, My City, My State")
+net.addRawNode(customer)# Insert the customer ID
+
+# Give them a device
+device=NetworkNode(
+ id="Unique Device ID",
+ displayName="Doe Family CPE",
+ parentId="Unique Customer ID",# must match the customer's ID
+ type=NodeType.device,
+ ipv4=["100.64.1.5/32"],# As many as you need, express networks as the network ID - e.g. 192.168.100.0/24
+ ipv6=["feed:beef::12/64"],# Same again. May be [] for none.
+ mac="00:00:5e:00:53:af"
+)
+net.addRawNode(device)
+
+
+
If the customer has multiple devices, you can add as many as you want - with ParentId continuing to match the parent customer’s id.
+
Once you have entered all of your customers, you can finish the integration:
+
net.prepareTree()# This is required, and builds parent-child relationships.
+net.createNetworkJson()# Create `network.json`
+net.createShapedDevices()# Create the `ShapedDevices.csv` file.
+
Creating a full hierarchy (with as many levels as you want) uses a similar strategy to flat networks—we recommend that you start by reading the “flat shaping” section above.
Then create an empty network graph (it will grow to represent your network):
+
net=NetworkGraph()
+
+
+
Now you can start to insert sites and access points. Sites and access points are inserted like customer or device nodes: they have a unique ID, and a ParentId. Customers can then use a ParentId of the site or access point beneath which they should be located.
+
For example, let’s create Site_1 and Site_2 - at the top of the tree:
When you attach a customer, you can specify a tree entry (e.g. Site_5) as a parent:
+
# Add the customer
+customer=NetworkNode(
+ id="Unique Customer ID",
+ displayName="The Doe Family",
+ parentId="Site_5",
+ type=NodeType.client,
+ download=100,# Download is in Mbit/second
+ upload=20,# Upload is in Mbit/second
+ address="1 My Road, My City, My State")
+net.addRawNode(customer)# Insert the customer ID
+
+# Give them a device
+device=NetworkNode(
+ id="Unique Device ID",
+ displayName="Doe Family CPE",
+ parentId="Unique Customer ID",# must match the customer's ID
+ type=NodeType.device,
+ ipv4=["100.64.1.5/32"],# As many as you need, express networks as the network ID - e.g. 192.168.100.0/24
+ ipv6=["feed:beef::12/64"],# Same again. May be [] for none.
+ mac="00:00:5e:00:53:af"
+)
+net.addRawNode(device)
+
+
+
Once you have entered all of your network topology and customers, you can finish the integration:
+
net.prepareTree()# This is required, and builds parent-child relationships.
+net.createNetworkJson()# Create `network.json`
+net.createShapedDevices()# Create the `ShapedDevices.csv` file.
+
+
+
You can also add a call to net.plotNetworkGraph(False) (use True to also include every customer; this can make for a HUGE file) to create a PDF file (currently named network.pdf.pdf) displaying your topology. The example shown here looks like this:
LibreQoS supports optional per‑circuit SQM overrides via the last column (sqm) of ShapedDevices.csv.
+
+
Accepted values:
+
+
Single token: cake, fq_codel, or none (applies to both directions)
+
Directional: down_sqm/up_sqm where each side is one of cake, fq_codel, none, or empty
+
+
+
Directional semantics:
+
+
Left token is download, right token is upload (e.g., cake/fq_codel)
+
Either side may be empty to leave that direction at default (e.g., cake/ or /fq_codel)
+
none disables the SQM qdisc for that direction
+
+
+
Normalization: Values are trimmed and lower‑cased; case is ignored on load
+
Defaults and fast‑queues: If a side is unspecified (empty) or the entire field is empty, the global default SQM applies for that side. The “fast queues to fq_codel” threshold is evaluated per direction when no explicit override is set.
You could theoretically throttle all unknown IPs until they are associated with a client. For example, you could limit every unknown to 1.5x0.5 with single entry in ShapedDevices.csv, until you associate them with an account. IPs need to be non-exact matches. So you can’t have two 192.168.1.1 entries, but you can have a 192.168.1.0/24 subnet and a 192.168.1.2/32 - they aren’t duplicates, and the LPM search is smart enough to pick the most exact match.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/src/README.html b/_build/html/src/README.html
new file mode 100644
index 00000000..00e91cb6
--- /dev/null
+++ b/_build/html/src/README.html
@@ -0,0 +1,140 @@
+
+
+
+
+
+
+
+
+ v1.4 (Alpha) — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
LibreQoS assigns circuits and sites to CPU queues using a simple, deterministic greedy binpacking approach. We continue to use Insight (lts) to provide weights when available, but assignments themselves are computed on each run without keeping long‑term state.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/src/TESTING-1.4.html b/_build/html/src/TESTING-1.4.html
new file mode 100644
index 00000000..7169e5d2
--- /dev/null
+++ b/_build/html/src/TESTING-1.4.html
@@ -0,0 +1,319 @@
+
+
+
+
+
+
+
+
+ How to Test V1.4 — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
By specifying libreqos at the end, git will ensure the folder name is lowercase.
+
+
Now that this is in main, you no longer need to switch git branch. If you were previously on the v1.4-pre-alpha-rust-integration branch, please switch to main with gitcheckoutmain;gitpull.
When Rust finishes installing, it will tell you to execute a command to place the Rust build tools into your path. You need to either execute this command or logout and back in again.
+
Once that’s done, change directory to /wherever_you_put_libreqos/src/, and run:
+
./build_rust.sh
+
+
+
This will take a while the first time, but it puts everything in the right place.
+Remember to run this command everytime after gitpull.
+
Now, run:
+
cd/src/rust
+cargobuild--all
+
+
+
Again, please run this command everytime after gitpull.
lqos_scheduler handles statistics and performs continuous refreshes of LibreQoS’ shapers, including pulling from any enabled CRM Integrations (UISP, Splynx).
+
+
On start: Run a full setup of queues
+
Every 10 seconds: Graph bandwidth and latency stats
+
Every 30 minutes: Update queues, pulling new configuration from CRM integration if enabled
You can setup lqosd and lqos_node_manager as daemons to keep running (there are example systemd files in the src/bin folder). Since v1.4 is under such heavy development, I recommend using screen to run detached instances - and make finding issues easier.
You can now point a web browser at http://a.b.c.d:9123 (replace a.b.c.d with the management IP address of your shaping server) and enjoy a real-time view of your network.
+
In the web browser, click ReloadLibreQoS to setup your shaping rules.
LibreQoS assigns circuits and sites to CPU queues using a simple, deterministic greedy binpacking approach. We continue to use Insight (lts) to provide weights when available, but assignments themselves are computed on each run without keeping long‑term state.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/src/error_handling/README.html b/_build/html/src/error_handling/README.html
new file mode 100644
index 00000000..707d3c48
--- /dev/null
+++ b/_build/html/src/error_handling/README.html
@@ -0,0 +1,160 @@
+
+
+
+
+
+
+
+
+ Comprehensively handling errors from the OS is a difficult job — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Comprehensively handling errors from the OS is a difficult job
The bakery implements TC commands required to build the HTB and CAKE structures.
+It also provides longer-term queue tracking, allowing for the “lazy” creation of queues.
+
It communicates with the rest of the system via the bus.
lazy_queues="Htb": All HTB bandwidth-limiting queues will be created when LibreQoS.py runs (including by the scheduler). This ensures that you don’t have a sudden burst of unshaped traffic. CAKE queues are created lazily, within 1 second of traffic being detected.
+
lazy_queues="Full": All queues are created lazily, within 1 second of traffic being detected.
+
+
If you set lazy_expire_seconds to a value greater than 0, the bakery will also remove queues that have not been
+used for that many seconds. This is useful for long-term idle queues that you don’t want to keep around forever. The
+default expiration time is 600 seconds (10 minutes). If you set it to 0, queues will never be removed.
+
+
It is NOT recommended to set lazy_expire_seconds to a very short time-period (under 60 seconds), as this can cause flapping.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/src/rust/lqos_bus/CONTRIBUTING.html b/_build/html/src/rust/lqos_bus/CONTRIBUTING.html
new file mode 100644
index 00000000..880d8002
--- /dev/null
+++ b/_build/html/src/rust/lqos_bus/CONTRIBUTING.html
@@ -0,0 +1,193 @@
+
+
+
+
+
+
+
+
+ Contributing to lqos_bus — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Contributions are accepted under: AGPL-3.0-or-laterWITHLicenseRef-LibreQoS-Exception.
+
The exception is defined in LICENSE as AGPLv3 §7 “Additional permissions” for:
+
+
LibreQoS Linking Exception (GPL-2.0-only combination with LibreQoS), and
+
LibreQoE Internal-Use Exception (internal proprietary combination and deployment by LibreQoE LLC).
+
+
+
By submitting a contribution (e.g., PR/patch), you affirm you have the right to do so and you agree to license your contribution under these terms, including the exceptions.
The bus acts as an intermediary through which lqosd and various clients communicate. The Python integration system, lqtop and other CLI tools use it to interact with lqosd.
+
The bus is intentionally not stable between releases. So if you integrate with it, you will need to update your integration every time you update lqosd. This:
+
+
Allows for rapid iteration on the back-end.
+
Avoids the need for version negotiation (CBOR tolerates unknown enum variants).
+
Uses CBOR serialization with length-prefixed chunked framing for large payloads.
+
+
+
If you’d like a stable API, please consider the HTTP API provided with Insight.
The LibreQoS Bus system is also separately licensed. We use the AGPL-3.0 license for the bus system, with the explicit exception that LibreQoS itself and all products produced by LibreQoE LLC are exempt and licensed separately.
+
We made this decision to ensure that the bus remains free and open source, and clients that add functionality to LibreQoS will also remain free and open source—even if you host it as a service. However, we do not want to force LibreQoS itself to be AGPL-3.0, as we want to allow for commercial use of LibreQoS itself.
+
Any contributions to the bus system must include permission to use this license, including “carve-outs” for LibreQoS itself and all products produced by LibreQoE LLC.
Declare a Major Version Break. This is a whole new setup that will require a new configuration and migration. We should avoid doing this very often.
+
+
You need to create a new folder, e.g. src/etc/v16.
+
You need to port as much of the old config as you are creating.
+
You need to update src/etc/migration.rs to include code to read a “v15” file and create a “v16” configuration.
+
This is a lot of work and should be a planned effort!
+
+
+
Declare an optional new version item. This is how you handle “oh, I needed to snoo the foo” - and add an optional configuration item - so nothing will snarl up because it isn’t there.
+
+
Find the section you want to include it in in src/etc/v15. If there isn’t one, create it using one of the others as a template and be sure to include the defaults. Add it into top_config as the type Option<MySnooFoo>.
+
Update example.toml to include what should go there.
+
Go into lqos_python and in lib.rs add a Python “getter” for the field. Remember to use iflet to read the Option and return a default if it isn’t present.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/src/rust/lqos_queue_tracker/src/queue_types/CAKE.html b/_build/html/src/rust/lqos_queue_tracker/src/queue_types/CAKE.html
new file mode 100644
index 00000000..83d0c02f
--- /dev/null
+++ b/_build/html/src/rust/lqos_queue_tracker/src/queue_types/CAKE.html
@@ -0,0 +1,159 @@
+
+
+
+
+
+
+
+
+ <no title> — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ways_collisions, if you are seeing a lot of these, it’s indicative of a ping flood of some kind.
+thresh 6Mbit
+target 5.0ms
+interval 100.0ms
+these are the bandwidth and codel settiings. On a vpn interface, or in a place where the typical rtt is to sydney and back, you can set rtt lower in cake, otherwise, don’t touch.
+pk_delay 440us
+av_delay 13us
+sp_delay 2us
+All these are ewmas (I forget the interval). pk_delay would be a good statistic to graph, tho I suspect that the highest peak delays would be on the lowest end plans, so peak delay by plan would pull out folk that were above average here.
+av_delay is pretty useless, like all averages, IMHO. Still I could be wrong.
+sp_delay = sparse delay and is an indicator of overload. Customers with the largest sparse delay would be interesting. Ideally this number never cracks 2ms.
+backlog - a persistent backlog is OK, but a sign that someone is using a torrent-like app, doing a big backup, or underprovisioned in some way. Seeing a persistent backlog in an AP on the other hand says the AP is overloaded.
+pkts
+bytes
+do what they say and are a summary statistic since invokation of cake.
+way_inds
+way_mis
+way_cols are indicators of how well the FQ is working, but not ver good ones.
+drops
+marks
+ack_drop
+in general I care about pkts, ack_drops, drops and marks, most, these are best plotted together on an invlog scale. When last I looked robert was combining drops and marks to treat as drops (which they are), but I am caring about the rise of ECN in general. As for the top 10 approach, the largest number of drops or marks relative to packets, would be useful.
+sp_flows 1
+bk_flows 1
+un_flows 0
+bulk_flows indicate large transfers. They have nothing to do with diffserv marks, they are just bulk.
+max_len - if this is greater than your MTU, GRO and GSO are loose on your network.
+Quantum varies as a function of bandwidth, it may be 300 is more optimal than an MTU even at higher bandwidths than we first tested cake at.
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/src/rust/lqos_setup/README-es.html b/_build/html/src/rust/lqos_setup/README-es.html
new file mode 100644
index 00000000..2b43e641
--- /dev/null
+++ b/_build/html/src/rust/lqos_setup/README-es.html
@@ -0,0 +1,165 @@
+
+
+
+
+
+
+
+
+ Configuración de LibreQoS — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Esta es la herramienta de configuración de LibreQoS, diseñada para ejecutarse automáticamente como parte del proceso de instalación con dpkg. Su objetivo principal es ayudar a los usuarios a establecer rápidamente una configuración mínima funcional de LibreQoS, asegurando que el sistema esté listo para operar con la menor intervención manual posible.
La herramienta de configuración de LibreQoS guía a los usuarios a través de los pasos esenciales necesarios para poner LibreQoS en funcionamiento. Simplifica el proceso inicial de configuramiento al proporcionar una interfaz guiada y automatiza la creación de los archivos de configuración necesarios.
La herramienta de configuración proporciona una Interfaz de Usuario en Texto construida con la librería Cursive. Esta interfaz permite a los usuarios navegar de manera interactiva por las opciones de configuración en la terminal, haciendo que el proceso de instalación sea sencillo y amigable.
Al ejecutar esta herramienta durante la instalación, LibreQoS garantiza que todas las configuraciones críticas estén definidas y que el sistema esté listo para su uso inmediato. La herramienta de configuración es una parte integral del sistema LibreQoS, agilizando la implementación y reduciendo el riesgo de errores de configuración.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/src/rust/lqos_setup/README.html b/_build/html/src/rust/lqos_setup/README.html
new file mode 100644
index 00000000..fc9529e2
--- /dev/null
+++ b/_build/html/src/rust/lqos_setup/README.html
@@ -0,0 +1,165 @@
+
+
+
+
+
+
+
+
+ LibreQoS Setup — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
This is the setup tool for LibreQoS, designed to be run automatically as part of the dpkg installation process. Its primary goal is to help users quickly establish a minimal working configuration for LibreQoS, ensuring that the system is ready for operation with minimal manual intervention.
The LibreQoS setup tool guides users through the essential configuration steps required to get LibreQoS up and running. It simplifies the initial setup process by providing a guided interface and automating the creation of necessary configuration files.
The setup tool provides a TUI (Text User Interface) built with the Cursive library. This interface allows users to navigate configuration options interactively in the terminal, making the setup process straightforward and user-friendly.
By running this tool during installation, LibreQoS ensures that all critical settings are defined and that the system is ready for immediate use. The setup tool is an integral part of the overall LibreQoS system, streamlining deployment and reducing the potential for misconfiguration.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/src/rust/lqos_stormguard/README.html b/_build/html/src/rust/lqos_stormguard/README.html
new file mode 100644
index 00000000..b1956966
--- /dev/null
+++ b/_build/html/src/rust/lqos_stormguard/README.html
@@ -0,0 +1,194 @@
+
+
+
+
+
+
+
+
+ LibreQoS StormGuard — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
[stormguard]
+enabled=true
+dry_run=true
+log_file="/tmp/stormguard.csv"# Optional
+targets=["CALVIN 1"]
+minimum_download_percentage=0.5# For 50% of download as minimum
+minimum_upload_percentage=0.5# For 50% of upload as minimum
+
+
+
+
+
Entry Name
+
Description
+
+
+
+
enabled
+
Enable or disable Tornado. Default: false
+
+
dry_run
+
If true, Tornado will not change the rate. It will only log what it would have done. Default: false
+
+
log_file
+
If set, a CSV will be appended with time (unix secs), download rate, upload rate entries. Default: absent
+
+
+
+
You can list as many sites as you want in the targets array. I strongly recommend dry_run for now, which just
+emits what it would have done to the console!
StormGuard maintains a ring-buffer of recent throughput, TCP retransmits and TCP round-trip times for each target site.
+These are updated once per second, when lqosd “ticks”. A second buffer maintains a moving average of a larger time period.
+
Each circuit also maintains a “current queue bandwidth”, which is adjusted dynamically. If dry_run is not set,
+this is applied directly to the HTB queue associated with the monitoring.
+
+
Warning: Do not apply this to HTB circuits that have a directly attached CAKE instance.
+
+
Periodically:
+
+
Saturation is calculated as current throughput / max throughput.
+
Live saturation is calculated as current throughput / current queue bandwidth.
+
Retransmits are set to either High, RisingFast, Rising, Stable, Falling, FallingFast.
+
RTT is set to either Rising, Stable or Falling.
+
+
These are fed through a decision matrix to determine if the queue bandwidth should be increased or decreased.
+
Changes have a “cool-down” following their application, during which monitoring will continue but no changes will be made.
+This is to prevent oscillation between two states.
Reciprocal mappings are created NOT automatically, you have to specify each mapping. When you are using “on a stick” mode, you need to redirect to the same interface.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/src/rust/lqosd/src/node_manager/js_build/README.html b/_build/html/src/rust/lqosd/src/node_manager/js_build/README.html
new file mode 100644
index 00000000..1f2e9050
--- /dev/null
+++ b/_build/html/src/rust/lqosd/src/node_manager/js_build/README.html
@@ -0,0 +1,136 @@
+
+
+
+
+
+
+
+
+ Site_build — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
This provides a common JavaScript library used by various internal and external portions
+of LibreQOS. Like LibreQoS, it is GNU General Purpose License v2 for distribution.
+
This project is licensed under the GNU General Public License v2.0 (GPL-2.0).
+However, we explicitly exempt other projects developed by LibreQoS from the copyleft requirements of the GPL-2.0, permitting their use of this project’s code under more permissive terms.
+
Any contributors to this project (but not any forks or adaptations for other projects)
+must assign copyright to LibreQoS and retain these exemptions.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_build/html/src/rust/xdp_iphash_to_cpu_cmdline/README.html b/_build/html/src/rust/xdp_iphash_to_cpu_cmdline/README.html
new file mode 100644
index 00000000..64ef5f98
--- /dev/null
+++ b/_build/html/src/rust/xdp_iphash_to_cpu_cmdline/README.html
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+
+
+ <no title> — LibreQoE documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/conf.py b/conf.py
index f1a62beb..3130a164 100644
--- a/conf.py
+++ b/conf.py
@@ -16,7 +16,7 @@ author = "LibreQoE, LLC"
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
-extensions = ["myst_parser"]
+extensions = ["myst_parser", "sphinxcontrib.mermaid"]
myst_enable_extensions = [
'substitution'
diff --git a/docs-es/index.rst b/docs-es/index.rst
index afed26f4..da8db1fd 100644
--- a/docs-es/index.rst
+++ b/docs-es/index.rst
@@ -36,7 +36,6 @@ Bienvenido a la documentación de LibreQoS
v2.0/insight-es
v2.0/api-es
- v2.0/lts-es
.. toctree::
:maxdepth: 1
diff --git a/docs-es/v2.0/configuration-advanced-es.md b/docs-es/v2.0/configuration-advanced-es.md
index 3222eaea..226a950c 100644
--- a/docs-es/v2.0/configuration-advanced-es.md
+++ b/docs-es/v2.0/configuration-advanced-es.md
@@ -68,7 +68,7 @@ echo "{}" > network.json
LibreQoS soporta **nodos virtuales** en `network.json` para agrupar y para monitoreo/agregación en la WebUI/Insight. Los nodos virtuales **no** se incluyen en el árbol físico de shaping HTB (no crean clases HTB y no aplican límites de ancho de banda).
-Para marcar un nodo como virtual, configura `"virtual": true` en ese nodo. (Compatibilidad heredada: `"type": "virtual"` también se reconoce, pero se recomienda `"virtual": true` para poder mantener un `"type"` real como `"Site"` o `"AP"`.)
+Para marcar un nodo como virtual, configura `"virtual": true` en ese nodo.
Ejemplo:
diff --git a/docs-es/v2.0/design-es.md b/docs-es/v2.0/design-es.md
index dc168e6a..4050a790 100644
--- a/docs-es/v2.0/design-es.md
+++ b/docs-es/v2.0/design-es.md
@@ -25,16 +25,6 @@ Si tu despliegue MPLS usa un patrón distinto, lo ideal es terminar el tráfico
Recomendamos usar protocolos como OSPF para definir rutas de bajo y alto costo entre el router de borde y el router/switch de distribución. La ruta de bajo costo debe pasar “a través” de las interfaces puente del shaper para que LibreQoS pueda observar y regular el tráfico. Por ejemplo, la ruta OSPF de bajo costo puede tener costo 1. El enlace de alto costo (respaldo) debe omitir por completo LibreQoS y configurarse con un costo mayor (por ejemplo 100 en OSPF) para que el tráfico solo tome ese camino cuando el puente de LibreQoS no esté operativo.
-### Opción 2: Spanning Tree Protocol (no recomendado)
-
-También puedes usar Spanning Tree Protocol con costos de ruta si OSPF u otro protocolo dinámico no es posible.
-
-```{note}
-Casi las mismas consideraciones aplican a la configuración alternativa que a la configuración oficialmente soportada.
-```
-
-Ten en cuenta que, si usas enlaces con distintos anchos de banda (por ejemplo, 10 Gbps a través de LibreQoS y 1 Gbps entre el switch central y el router de borde), deberás ajustar con mayor cuidado los costos de STP.
-
## Despliegue de laboratorio (opcional)
Cuando pruebes LibreQoS por primera vez puedes desplegar un laboratorio a pequeña escala para verlo en acción.

diff --git a/docs-es/v2.0/integrations-es.md b/docs-es/v2.0/integrations-es.md
index ff658c56..15050cbc 100644
--- a/docs-es/v2.0/integrations-es.md
+++ b/docs-es/v2.0/integrations-es.md
@@ -37,11 +37,6 @@ Cuando hay integraciones habilitadas:
- `network.json` también puede sobrescribirse según configuración (por ejemplo `always_overwrite_network_json`).
- Las ediciones manuales pueden sobrescribirse en el siguiente ciclo de refresco.
-## ¿Necesita la referencia completa heredada?
-
-El contenido detallado completo se conserva aquí:
-- [Referencia de integraciones (detallada)](integrations-reference-es.md)
-
## Páginas relacionadas
- [Quickstart](quickstart-es.md)
diff --git a/docs-es/v2.0/integrations-reference-es.md b/docs-es/v2.0/integrations-reference-es.md
index 6a30fb16..a52a6b25 100644
--- a/docs-es/v2.0/integrations-reference-es.md
+++ b/docs-es/v2.0/integrations-reference-es.md
@@ -298,7 +298,7 @@ commit_bandwidth_multiplier = 0.98 # Establecer mínimo al 98% del máximo (CIR
ipv6_with_mikrotik = false # Habilitar si usa DHCPv6 con MikroTik
always_overwrite_network_json = false # Establecer true para reconstruir topología en cada ejecución
exception_cpes = [] # Excepciones de CPE en formato ["cpe:parent"]
-squash_sites = [] # Opcional: sitios a compactar (flujo legacy de full)
+squash_sites = [] # Opcional: sitios a compactar
enable_squashing = false # Opcional: habilita lógica adicional de compactación
do_not_squash_sites = [] # Opcional: sitios excluidos de compactación
ignore_calculated_capacity = false # Opcional: prioriza capacidad configurada sobre la calculada
diff --git a/docs-es/v2.0/lts-es.md b/docs-es/v2.0/lts-es.md
deleted file mode 100644
index c27f8c8e..00000000
--- a/docs-es/v2.0/lts-es.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Nomenclatura LTS heredada (deprecado)
-
-```{warning}
-LTS está deprecado y fue reemplazado por LibreQoS Insight.
-Para despliegues actuales y nuevas suscripciones, use la documentación de Insight:
-[Insight](insight-es.md)
-```
-
-## Nota de migración
-
-Si tiene referencias heredadas a LTS en runbooks/documentación interna:
-
-- Reemplácelas por referencias a Insight.
-- Use [insight-es.md](insight-es.md) para comportamiento y flujos actuales.
-- Use [api-es.md](api-es.md) para detalles de API de nodo (`/api-docs` en su nodo es la fuente de verdad).
-- En algunas rutas UI/código todavía aparecen nombres históricos como `lts_trial` o `config_lts`; en versiones actuales se refieren a flujos de Insight.
-
-Las instrucciones heredadas de onboarding de LTS se removieron para evitar confusión en despliegues nuevos.
diff --git a/docs-es/v2.0/node-manager-ui-es.md b/docs-es/v2.0/node-manager-ui-es.md
index d97a94fa..018433ea 100644
--- a/docs-es/v2.0/node-manager-ui-es.md
+++ b/docs-es/v2.0/node-manager-ui-es.md
@@ -65,10 +65,6 @@ Si ocurre:
journalctl -u lqosd --since "10 minutes ago"
```
-## Nota de nomenclatura heredada
-
-Algunos identificadores internos todavía usan nombres históricos `lts_*`. Operativamente, en versiones actuales se refieren a flujos de Insight.
-
## Páginas relacionadas
- [Componentes](components-es.md)
diff --git a/docs-es/v2.0/quickstart-es.md b/docs-es/v2.0/quickstart-es.md
index e02b40ce..9b528cbc 100644
--- a/docs-es/v2.0/quickstart-es.md
+++ b/docs-es/v2.0/quickstart-es.md
@@ -119,8 +119,3 @@ Recomendado solo para redes menores a 100 suscriptores.
- [Modos de operación y fuente de verdad](operating-modes-es.md)
- [Escalado y diseño de topología](scale-topology-es.md)
- [Solución de problemas](troubleshooting-es.md)
-
-## Instalación para desarrolladores (No recomendada para operadores)
-
-La instalación basada en Git está aquí:
-- [Git Install (Para Desarrolladores)](git-install-es.md)
diff --git a/docs-es/v2.0/stormguard-es.md b/docs-es/v2.0/stormguard-es.md
index 52a09bef..d3189d1f 100644
--- a/docs-es/v2.0/stormguard-es.md
+++ b/docs-es/v2.0/stormguard-es.md
@@ -2,6 +2,10 @@
StormGuard es el subsistema de ajuste adaptativo de colas de LibreQoS para eventos de congestión y calidad.
+> **Advertencia importante de alcance**
+> StormGuard está pensado para casos de uso específicos, como controlar congestión en enlaces WAN de ancho de banda variable (por ejemplo redes marítimas), o para un número pequeño de puntos de acceso con capacidades muy variables.
+> No está pensado para gestionar decenas o cientos de nodos al mismo tiempo.
+
## Qué hace StormGuard
- Monitorea señales en tiempo real (throughput, métricas RTT/pérdida y contexto de saturación).
diff --git a/docs/v2.0/configuration-advanced.md b/docs/v2.0/configuration-advanced.md
index 6d7a3fa8..e978bb36 100644
--- a/docs/v2.0/configuration-advanced.md
+++ b/docs/v2.0/configuration-advanced.md
@@ -116,7 +116,7 @@ echo "{}" > network.json
LibreQoS supports **virtual nodes** in `network.json` for organizational grouping and monitoring/aggregation in the WebUI/Insight. Virtual nodes are **not** included in the physical HTB shaping tree (they won’t create HTB classes and won’t enforce bandwidth limits).
-To mark a node as virtual, set `"virtual": true` on that node. (Legacy compatibility: `"type": "virtual"` is also recognized, but `"virtual": true` is recommended so you can keep a real `"type"` like `"Site"` or `"AP"`.)
+To mark a node as virtual, set `"virtual": true` on that node.
Example:
diff --git a/docs/v2.0/design.md b/docs/v2.0/design.md
index 0790b13a..468f7fdb 100644
--- a/docs/v2.0/design.md
+++ b/docs/v2.0/design.md
@@ -25,16 +25,6 @@ If you use MPLS with a different tag pattern, you would ideally want to terminat
We recommend using dynamic routing protocols such as OSPF to create a high cost and low cost path between the edge router and core distribution router/switch. The low cost path should pass "through" the LibreQoS shaper bridge interfaces to allow LibreQoS to observe and shape traffic. For example, a low cost OSPF path may be set to a value of 1. The high-cost (backup) link would completely bypass LibreQoS, being set to a higher cost (perhaps 100 for OSPF) to ensure that traffic only takes that path when the LibreQoS shaper bridge is not operational.
-### Option 2: Using Spanning Tree Protocol (Not Recommended)
-
-You can also use the Spanning Tree Protocol with path costs if OSPF or another dynamic routing protocol is not an option.
-
-```{note}
-Most of the same considerations apply to the alternate configuration as they do to the officially supported configuation
-```
-
-Keep in mind that if you use different bandwidth links, for example, 10 Gbps through LibreQoS, and 1 Gbps between core switch and edge router, you may need to be more intentional with your STP costs.
-
## Testbed Deployment (Optional)
When you are first testing out LibreQoS, you can deploy a small-scale testbed to see it in action on a test network.

diff --git a/docs/v2.0/integrations-netzur.md b/docs/v2.0/integrations-netzur.md
index efa277f9..670bc895 100644
--- a/docs/v2.0/integrations-netzur.md
+++ b/docs/v2.0/integrations-netzur.md
@@ -1,21 +1,33 @@
# Netzur Integration
-## Summary
+Netzur deployments expose subscriber and zone inventories via a REST endpoint secured with a Bearer token. Configure `/etc/lqos.conf` as follows:
-Use this when Netzur is your CRM/NMS source of truth.
+```ini
+[netzur_integration]
+enable_netzur = true
+api_key = "your-netzur-token"
+api_url = "https://netzur.example.com/api/libreqos"
+timeout_secs = 60
+use_mikrotik_ipv6 = false
+```
-## Basic Setup
+- `enable_netzur` toggles automatic imports by `lqos_scheduler`.
+- `api_key` is the Bearer token generated inside Netzur.
+- `api_url` must return JSON containing `zones` (mapped to sites) and `customers` (mapped to client circuits and devices).
+- `timeout_secs` overrides the default HTTP timeout (60 seconds) when the API is slow.
+- `use_mikrotik_ipv6` enriches subscriber devices with IPv6 prefixes discovered via `mikrotikDHCPRouterList.csv`.
-1. Configure `[netzur_integration]` values in `/etc/lqos.conf`.
-2. Run a manual import test.
-3. Enable scheduler-driven sync.
+Run a manual import with:
-## Operational Notes
+```bash
+python3 integrationNetzur.py
+```
-- Integration regenerates `ShapedDevices.csv`.
-- `network.json` updates depend on overwrite settings.
+The integration regenerates `ShapedDevices.csv` and, unless `always_overwrite_network_json` is disabled, updates `network.json`. Adjust the Integration → Common settings if you need to preserve an existing network map between Netzur syncs.
-## Full Reference
-- [Detailed Netzur Reference](integrations-reference.md#netzur-integration)
+## Related Pages
+
+- [CRM/NMS Integrations](integrations.md)
- [Operating Modes and Source of Truth](operating-modes.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/docs/v2.0/integrations-powercode.md b/docs/v2.0/integrations-powercode.md
index 7a1654d6..2105d67d 100644
--- a/docs/v2.0/integrations-powercode.md
+++ b/docs/v2.0/integrations-powercode.md
@@ -1,21 +1,21 @@
# Powercode Integration
-## Summary
+First, set the relevant parameters for Powercode (powercode_api_key, powercode_api_url, etc.) in `/etc/lqos.conf`.
-Use this when Powercode is your CRM/NMS source of truth.
+To test the Powercode Integration, use
-## Basic Setup
+```shell
+python3 integrationPowercode.py
+```
-1. Configure Powercode integration settings in `/etc/lqos.conf`.
-2. Run a manual import test.
-3. Enable scheduler-driven sync.
+On the first successful run, it will create a ShapedDevices.csv file.
+You can modify the network.json file manually to reflect Site/AP bandwidth limits.
+ShapedDevices.csv will be overwritten every time the Powercode integration is run.
+You have the option to run integrationPowercode.py automatically on boot and every X minutes (set by the parameter `queue_refresh_interval_mins`), which is highly recommended. This can be enabled by setting ```enable_powercode = true``` in `/etc/lqos.conf`.
-## Operational Notes
-- `ShapedDevices.csv` is regenerated on sync.
-- Review how you want `network.json` handled for your topology workflow.
+## Related Pages
-## Full Reference
-
-- [Detailed Powercode Reference](integrations-reference.md#powercode-integration)
+- [CRM/NMS Integrations](integrations.md)
- [Operating Modes and Source of Truth](operating-modes.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/docs/v2.0/integrations-reference.md b/docs/v2.0/integrations-reference.md
index f409da6c..77e9cb28 100644
--- a/docs/v2.0/integrations-reference.md
+++ b/docs/v2.0/integrations-reference.md
@@ -301,7 +301,7 @@ commit_bandwidth_multiplier = 0.98 # Set minimum to 98% of maximum (CIR)
ipv6_with_mikrotik = false # Enable if using DHCPv6 with MikroTik
always_overwrite_network_json = false # Set true to rebuild topology each run
exception_cpes = [] # CPE exceptions in ["cpe:parent"] format
-squash_sites = [] # Optional: sites to squash (legacy full strategy behavior)
+squash_sites = [] # Optional: sites to squash
enable_squashing = false # Optional: enable AP/single-entry squashing logic
do_not_squash_sites = [] # Optional: never squash these sites
ignore_calculated_capacity = false # Optional: keep configured capacities even if calculated differs
diff --git a/docs/v2.0/integrations-sonar.md b/docs/v2.0/integrations-sonar.md
index 8ab4edd8..551ab363 100644
--- a/docs/v2.0/integrations-sonar.md
+++ b/docs/v2.0/integrations-sonar.md
@@ -1,21 +1,22 @@
# Sonar Integration
-## Summary
+First, set the relevant parameters for Sonar (sonar_api_key, sonar_api_url, etc.) in `/etc/lqos.conf`.
-Use this when Sonar is your CRM/NMS source of truth.
+To test the Sonar Integration, use
-## Basic Setup
+```shell
+python3 integrationSonar.py
+```
-1. Configure Sonar integration settings in `/etc/lqos.conf`.
-2. Run a manual import test.
-3. Enable scheduler-driven sync.
+On the first successful run, it will create a ShapedDevices.csv file.
+If a network.json file exists, it will not be overwritten, unless you set ```always_overwrite_network_json = true```.
+You can modify the network.json file to more accurately reflect bandwidth limits.
+ShapedDevices.csv will be overwritten every time the Sonar integration is run.
+You have the option to run integrationSonar.py automatically on boot and every X minutes (set by the parameter `queue_refresh_interval_mins`), which is highly recommended. This can be enabled by setting ```enable_sonar = true``` in `/etc/lqos.conf`.
-## Operational Notes
-- `ShapedDevices.csv` is regenerated on sync.
-- `network.json` behavior depends on overwrite settings.
+## Related Pages
-## Full Reference
-
-- [Detailed Sonar Reference](integrations-reference.md#sonar-integration)
+- [CRM/NMS Integrations](integrations.md)
- [Operating Modes and Source of Truth](operating-modes.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/docs/v2.0/integrations-splynx.md b/docs/v2.0/integrations-splynx.md
index ec1aeae9..ea6248bb 100644
--- a/docs/v2.0/integrations-splynx.md
+++ b/docs/v2.0/integrations-splynx.md
@@ -1,22 +1,116 @@
# Splynx Integration
-## Summary
+> **⚠️ Breaking Change Notice**: Prior to v1.5-RC-2, the default Splynx strategy was `full`. Starting with v1.5-RC-2, the default strategy is `ap_only` for improved CPU performance. If you require the previous behavior, explicitly set `strategy = "full"` in your Splynx configuration section.
-Use this when Splynx is your CRM/NMS source of truth.
+First, set the relevant parameters for Splynx (splynx_api_key, splynx_api_secret, etc.) in `/etc/lqos.conf`.
-## Basic Setup
+### Topology Strategies
-1. Configure Splynx settings in `/etc/lqos.conf`.
-2. Select topology strategy (`flat`, `ap_only`, `ap_site`, `full`).
-3. Enable automatic sync and restart scheduler.
+LibreQoS supports multiple topology strategies for Splynx integration to balance CPU performance with network hierarchy needs:
-## Operational Notes
+| Strategy | Description | CPU Impact | Use Case |
+|----------|-------------|------------|----------|
+| `flat` | Only shapes subscribers, no hierarchy | Lowest | Maximum performance, simple subscriber-only shaping |
+| `ap_only` | Single layer: AP → Clients | Low | **Default**. Best balance of performance and structure |
+| `ap_site` | Two layers: Site → AP → Clients | Medium | Site-level aggregation with moderate complexity |
+| `full` | Complete topology mapping | Highest | Full network hierarchy representation |
-- `ShapedDevices.csv` is regenerated each sync.
-- `network.json` overwrite depends on `always_overwrite_network_json`.
-- Use WebUI Integration settings for day-to-day adjustments.
+Configure the strategy in `/etc/lqos.conf` under the `[splynx_integration]` section:
-## Full Reference
+```ini
+[splynx_integration]
+# ... other splynx settings ...
+strategy = "ap_only"
+```
-- [Detailed Splynx Reference](integrations-reference.md#splynx-integration)
+**Performance Considerations:**
+- `flat` and `ap_only` strategies significantly reduce CPU load by limiting network depth
+- Choose `ap_only` for most deployments unless you need site-level traffic aggregation
+- Only use `full` if you require complete network topology representation and have adequate CPU resources
+
+### Promote to Root Nodes (Performance Optimization)
+
+When using `full` topology strategy, you may encounter CPU performance bottlenecks where all traffic flows through a single root site, limiting throughput to what one CPU core can handle.
+
+The **promote_to_root** feature solves this by promoting specific sites to root-level nodes, distributing traffic shaping across multiple CPU cores.
+
+**Configuration:**
+1. Navigate to Integration → Common in the WebUI
+2. In the "Promote to Root Nodes" field, enter one site name per line:
+```
+Remote_Site_Alpha
+Remote_Site_Beta
+Datacenter_West
+```
+
+**Benefits:**
+- Eliminates single-CPU bottleneck for networks with remote sites
+- Distributes traffic shaping across multiple CPU cores
+- Improves overall network performance for large topologies
+- Works with both Splynx and UISP integrations
+
+**When to Use:**
+- Networks with multiple high-capacity remote sites
+- When using `full` topology strategy and experiencing CPU limitations
+- Large networks where root site traffic exceeds single-core capacity
+
+### Splynx API Access
+
+The Splynx Integration uses Basic authentication. For using this type of authentication, please make sure you enable [Unsecure access](https://splynx.docs.apiary.io/#introduction/authentication) in your Splynx API key settings. Also the Splynx API key should be granted access to the necessary permissions.
+
+| Category | Name | Permission |
+|----------------|------------------------------|------------|
+| Tariff Plans | Internet | View |
+| FUP | Compiler | View |
+| FUP | Policies | View |
+| FUP | Capped Data | View |
+| FUP | CAP Tariff | View |
+| FUP | FUP Limits | View |
+| Customers | Customer | View |
+| Customers | Customers Online | View |
+| Customers | Customer Internet services | View |
+| Networking | Routers | View |
+| Networking | Router contention | View |
+| Networking | MikroTik | View |
+| Networking | Monitoring | View |
+| Networking | Network Sites | View |
+| Networking | IPv4 Networks | View |
+| Networking | IPv4 Networks IP | View |
+| Networking | CPE | View |
+| Networking | CPE AP | View |
+| Networking | IPv6 Networks | View |
+| Networking | IPv6 Networks IP (Addresses) | View |
+| Administration | Locations | View |
+
+To test the Splynx Integration, use
+
+```shell
+python3 integrationSplynx.py
+```
+
+On the first successful run, it will create a ShapedDevices.csv file and network.json.
+ShapedDevices.csv will be overwritten every time the Splynx integration is run.
+
+To ensure the network.json is always overwritten with the newest version pulled in by the integration, please edit `/etc/lqos.conf` with the command `sudo nano /etc/lqos.conf`.
+Edit the file to set the value of `always_overwrite_network_json` to `true`.
+Then, run `sudo systemctl restart lqosd`.
+
+You have the option to run integrationSplynx.py automatically on boot and every X minutes (set by the parameter `queue_refresh_interval_mins`), which is highly recommended. This can be enabled by setting ```enable_splynx = true``` under the ```[splynx_integration]``` section in `/etc/lqos.conf`.
+Once set, run `sudo systemctl restart lqos_scheduler`.
+
+### Splynx Overrides
+
+You can also modify the the file `integrationSplynxBandwidths.csv` to override the default bandwidths for each Node (Site, AP).
+
+A template is available in the `/opt/libreqos/src` folder. To utilize the template, copy the file `integrationSplynxBandwidths.template.csv` (removing the `.template` part of the filename) and set the appropriate information inside each file. For example, if you want to change the set bandwidth for a site, you would do:
+```
+sudo cp /opt/libreqos/src/integrationSplynxBandwidths.template.csv /opt/libreqos/src/integrationSplynxBandwidths.csv
+```
+And edit the CSV using LibreOffice or your preferred CSV editor.
+
+
+## Related Pages
+
+- [CRM/NMS Integrations](integrations.md)
- [Operating Modes and Source of Truth](operating-modes.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/docs/v2.0/integrations-uisp.md b/docs/v2.0/integrations-uisp.md
index ed49fb5b..dfdd0f96 100644
--- a/docs/v2.0/integrations-uisp.md
+++ b/docs/v2.0/integrations-uisp.md
@@ -1,22 +1,195 @@
# UISP Integration
-## Summary
+First, set the relevant parameters for UISP in `/etc/lqos.conf`.
-Use this when UISP is your CRM/NMS source of truth.
+### Topology Strategies
-## Basic Setup
+LibreQoS supports multiple topology strategies for UISP integration to balance CPU performance with network hierarchy needs:
-1. Configure UISP settings in `/etc/lqos.conf`.
-2. Choose topology strategy and suspension handling strategy.
-3. Enable automatic sync and restart scheduler.
+| Strategy | Description | CPU Impact | Use Case |
+|----------|-------------|------------|----------|
+| `flat` | Only shapes subscribers by service plan speed | Lowest | Maximum performance, simple subscriber-only shaping |
+| `ap_only` | Shapes by service plan and Access Point | Low | Good balance of performance and AP-level control |
+| `ap_site` | Shapes by service plan, Access Point, and Site | Medium | Site-level aggregation with moderate complexity |
+| `full` | Shapes entire network including backhauls, Sites, APs, and clients | Highest | **Recommended for most deployments**. Complete network hierarchy with backhaul awareness |
-## Operational Notes
+**Choosing the Right Strategy:**
+- Use `full` for most deployments to get complete network topology awareness including backhaul links
+- Use `ap_site` if you need site-level control but don't need backhaul shaping
+- Use `ap_only` for better performance when site aggregation isn't needed
+- Use `flat` only when maximum performance is critical and you don't need any hierarchy
-- `ShapedDevices.csv` is regenerated each sync.
-- `network.json` overwrite depends on `always_overwrite_network_json`.
-- Use WebUI for operational changes; treat file edits as temporary in integration mode.
+**Performance Note:** When using `full` strategy with large networks, consider using `promote_to_root` to distribute CPU load across multiple cores.
-## Full Reference
+### Promote to Root Nodes (Performance Optimization)
-- [Detailed UISP Reference](integrations-reference.md#uisp-integration)
+When using `full` topology strategy, traffic can bottleneck on a single root node/CPU core.
+
+The `promote_to_root` feature can reduce this by promoting selected sites to root-level nodes so load is distributed.
+
+Configuration:
+1. Navigate to `Configuration -> Integrations` in WebUI.
+2. In `Promote to Root Nodes`, enter one site per line.
+
+Example:
+```
+Remote_Site_Alpha
+Remote_Site_Beta
+Datacenter_West
+```
+
+When to use:
+- Multi-site networks with high-capacity remote sites.
+- `full` strategy deployments showing single-core saturation.
+
+### Suspension Handling Strategies
+
+Configure how LibreQoS handles suspended customer accounts:
+
+| Strategy | Description | Use Case |
+|----------|-------------|----------|
+| `none` | Do not handle suspensions | When suspension handling is managed elsewhere |
+| `ignore` | Do not add suspended customers to network map | Reduces queue count and improves performance for networks with many suspended accounts |
+| `slow` | Limit suspended customers to 0.1 Mbps | Maintains minimal connectivity for suspended accounts (e.g., payment portals) |
+
+**Choosing a Suspension Strategy:**
+- Use `none` if your edge router or another system handles suspensions
+- Use `ignore` to reduce system load by not creating queues for suspended customers
+- Use `slow` to maintain minimal connectivity (useful for payment portals or service messages)
+
+### Burst
+
+- In UISP, Download Speed and Upload Speed are configured in Mbps (for example, 100 Mbps).
+- In UISP, Download Burst and Upload Burst are configured in kilobytes per second (kB/s).
+- Conversion and shaping:
+ - burst_mbps = kB/s × 8 / 1000
+ - Download Min = Download Speed (Mbps) × commit_bandwidth_multiplier
+ - Download Max = (Download Speed (Mbps) + burst_mbps) × bandwidth_overhead_factor
+ - Upload Min/Max are computed the same way from Upload Speed (Mbps) and Upload Burst (kB/s)
+- Example:
+ - UISP values: Download Speed = 100 Mbps, Download Burst = 12,500 kB/s
+ - Burst adds 12,500 × 8 / 1000 = 100 Mbps
+ - Download Min = 100 × commit_bandwidth_multiplier
+ - Download Max = (100 + 100) × bandwidth_overhead_factor
+- Quick reference (burst kB/s → added Mbps):
+ - 6,250 kB/s → +50 Mbps
+ - 12,500 kB/s → +100 Mbps
+ - 25,000 kB/s → +200 Mbps
+- Notes:
+ - Leave burst empty/null in UISP to disable burst.
+ - If suspended_strategy is set to slow, both Min and Max are set to 0.1 Mbps.
+
+### Configuration Example
+
+```ini
+[uisp_integration]
+# Core Settings
+enable_uisp = true
+token = "your-api-token-here"
+url = "https://uisp.your_domain.com"
+site = "Root_Site_Name" # Root site for topology perspective
+
+# Topology Strategy (see table above)
+strategy = "full" # Recommended for most deployments
+
+# Suspension Handling (see table above)
+suspended_strategy = "none"
+
+# Capacity Adjustments
+# UISP's reported AP capacities can be optimistic
+airmax_capacity = 0.65 # Use 65% of reported AirMax capacity
+ltu_capacity = 0.95 # Use 95% of reported LTU capacity
+
+# Site Management
+exclude_sites = [] # Sites to exclude, e.g., ["Test_Site", "Lab_Site"]
+use_ptmp_as_parent = true # For sites branched off PtMP Access Points
+
+# Bandwidth Adjustments
+bandwidth_overhead_factor = 1.15 # Give customers 15% above plan speed
+commit_bandwidth_multiplier = 0.98 # Set minimum to 98% of maximum (CIR)
+
+# Advanced Options
+ipv6_with_mikrotik = false # Enable if using DHCPv6 with MikroTik
+always_overwrite_network_json = false # Set true to rebuild topology each run
+exception_cpes = [] # CPE exceptions in ["cpe:parent"] format
+squash_sites = [] # Optional: sites to squash
+enable_squashing = false # Optional: enable AP/single-entry squashing logic
+do_not_squash_sites = [] # Optional: never squash these sites
+ignore_calculated_capacity = false # Optional: keep configured capacities even if calculated differs
+insecure_ssl = false # Optional: ignore UISP TLS certificate validation
+```
+
+### UISP Advanced/Operational Options
+
+The following UISP options are available in current builds and WebUI (Node Manager) config editors:
+
+- `exclude_sites`: list of site names to exclude from import.
+- `exception_cpes`: list of `cpe:parent` overrides for ambiguous parent assignment.
+- `squash_sites`: optional list of sites to squash in full strategy workflows.
+- `enable_squashing`: enables additional squashing behavior where supported.
+- `do_not_squash_sites`: explicit exclusions from squashing.
+- `use_ptmp_as_parent`: prefer PtMP AP as parent for relevant topology paths.
+- `ignore_calculated_capacity`: prefer configured capacities instead of integration-calculated values.
+- `insecure_ssl`: disables TLS certificate verification for UISP API calls.
+
+Recommended use:
+1. Keep `insecure_ssl = false` unless you have a known internal PKI/self-signed requirement.
+2. Use `exclude_sites` and `do_not_squash_sites` first for safer topology changes.
+3. Apply `squash_sites`/`enable_squashing` incrementally and validate queue placement after each change.
+
+To test the UISP Integration, use
+
+```shell
+cd /opt/libreqos/src
+sudo /opt/libreqos/src/bin/uisp_integration
+```
+
+On the first successful run, it will create a network.json and ShapedDevices.csv file.
+If a network.json file exists, it will not be overwritten, unless you set ```always_overwrite_network_json = true```.
+
+ShapedDevices.csv will be overwritten every time the UISP integration is run.
+
+To ensure the network.json is always overwritten with the newest version pulled in by the integration, please edit `/etc/lqos.conf` with the command `sudo nano /etc/lqos.conf`.
+Edit the file to set the value of `always_overwrite_network_json` to `true`.
+Then, run `sudo systemctl restart lqosd`.
+
+You have the option to run integrationUISP.py automatically on boot and every X minutes (set by the parameter `queue_refresh_interval_mins`), which is highly recommended. This can be enabled by setting ```enable_uisp = true``` in `/etc/lqos.conf`. Once set, run `sudo systemctl restart lqos_scheduler`.
+
+### UISP Overrides
+
+You can also modify the the following files to more accurately reflect your network:
+- integrationUISPbandwidths.csv
+- integrationUISProutes.csv
+
+Each of the files above have templates available in the `/opt/libreqos/src` folder. If you don't find them there, you can navigate [here](https://github.com/LibreQoE/LibreQoS/tree/develop/src). To utilize the template, copy the file (removing the `.template` part of the filename) and set the appropriate information inside each file.
+For example, if you want to change the set bandwidth for a site, you would do:
+```
+sudo cp /opt/libreqos/src/integrationUISPbandwidths.template.csv /opt/libreqos/src/integrationUISPbandwidths.csv
+```
+And edit the CSV using LibreOffice or your preferred CSV editor.
+
+#### UISP Route Overrides
+
+The default cost between nodes is typically 10. The integration creates a dot graph file `/opt/libreqos/src/graph.dot` which can be rendered using [Graphviz](https://dreampuf.github.io/GraphvizOnline/). This renders a map with the associated costs of all links.
+
+
+
+Say you have Site 1, Site 2, and Site 3.
+A backup path exists between Site 1 and Site 3, but is not the preferred path.
+Your preference is Site 1 > Site 2 > Site 3, but the integration by default connects Site 1 > Site 3 directly.
+
+To fix this, add a cost above the default for the path between Site 1 and Site 3.
+```
+Site 1, Site 3, 100
+Site 3, Site 1, 100
+```
+With this, data will flow Site 1 > Site 2 > Site 3.
+
+To make the change, perform a reload of the integration with ```sudo systemctl restart lqos_scheduler```.
+
+
+## Related Pages
+
+- [CRM/NMS Integrations](integrations.md)
- [Operating Modes and Source of Truth](operating-modes.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/docs/v2.0/integrations-visp.md b/docs/v2.0/integrations-visp.md
index b3feadea..0287d787 100644
--- a/docs/v2.0/integrations-visp.md
+++ b/docs/v2.0/integrations-visp.md
@@ -1,21 +1,44 @@
# VISP Integration
-## Summary
+First, set the relevant parameters for VISP in `/etc/lqos.conf`:
-Use this when VISP is your CRM/NMS source of truth.
+```ini
+[visp_integration]
+enable_visp = true
+client_id = "your-client-id"
+client_secret = "your-client-secret"
+username = "appuser-username"
+password = "appuser-password"
+# Optional: leave unset/blank to auto-select first ISP ID returned by token payload
+# isp_id = 0
+timeout_secs = 20
+# Optional: used for online session enrichment
+# online_users_domain = ""
+```
-## Basic Setup
+Notes:
+- VISP import is GraphQL-based and currently defaults to a flat topology strategy.
+- The integration writes `ShapedDevices.csv` every run.
+- `network.json` is only overwritten when `always_overwrite_network_json = true` (under `[integration_common]`).
+- VISP auth tokens are cached in `/.visp_token_cache_*.json`.
-1. Configure `[visp_integration]` credentials in `/etc/lqos.conf`.
-2. Run a manual import test.
-3. Enable scheduler-driven sync.
+Run a manual import with:
-## Operational Notes
+```bash
+python3 integrationVISP.py
+```
-- `ShapedDevices.csv` is rewritten each run.
-- `network.json` is overwritten only when enabled in integration common settings.
+To run automatically through `lqos_scheduler`, set:
+- `[visp_integration] enable_visp = true`
+- then restart scheduler:
-## Full Reference
+```bash
+sudo systemctl restart lqos_scheduler
+```
-- [Detailed VISP Reference](integrations-reference.md#visp-integration)
+
+## Related Pages
+
+- [CRM/NMS Integrations](integrations.md)
- [Operating Modes and Source of Truth](operating-modes.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/docs/v2.0/integrations-wispgate.md b/docs/v2.0/integrations-wispgate.md
index c8883b3c..fae22085 100644
--- a/docs/v2.0/integrations-wispgate.md
+++ b/docs/v2.0/integrations-wispgate.md
@@ -1,21 +1,37 @@
# WISPGate Integration
-## Summary
+First, set the relevant parameters for WISPGate in `/etc/lqos.conf`.
+There should be a section as follows:
-Use this when WISPGate is your CRM/NMS source of truth.
+```
+[wispgate_integration]
+enable_wispgate = false
+wispgate_api_token = "token"
+wispgate_api_url = "https://your_wispgate_url.com"
+```
-## Basic Setup
+If the section is missing, you can add it by copying the section above.
+Set the appropriate values for wispgate_api_token and wispgate_api_url, then save the file.
-1. Configure WISPGate integration settings in `/etc/lqos.conf`.
-2. Run a manual import test.
-3. Enable scheduler-driven sync.
+To test the WISPGate Integration, use
-## Operational Notes
+```shell
+python3 integrationWISPGate.py
+```
-- `ShapedDevices.csv` is regenerated on sync.
-- `network.json` behavior depends on your overwrite settings.
+On the first successful run, it will create a ShapedDevices.csv file and network.json.
+ShapedDevices.csv will be overwritten every time the WISPGate integration is run.
-## Full Reference
+To ensure the network.json is always overwritten with the newest version pulled in by the integration, please edit `/etc/lqos.conf` with the command `sudo nano /etc/lqos.conf`.
+Edit the file to set the value of `always_overwrite_network_json` to `true`.
+Then, run `sudo systemctl restart lqosd`.
-- [Detailed WISPGate Reference](integrations-reference.md#wispgate-integration)
+You have the option to run integrationWISPGate.py automatically on boot and every X minutes (set by the parameter `queue_refresh_interval_mins`), which is highly recommended. This can be enabled by setting ```enable_wispgate = true``` in `/etc/lqos.conf`.
+Once set, run `sudo systemctl restart lqos_scheduler`.
+
+
+## Related Pages
+
+- [CRM/NMS Integrations](integrations.md)
- [Operating Modes and Source of Truth](operating-modes.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/docs/v2.0/integrations.md b/docs/v2.0/integrations.md
index a903b7db..7ed9df2c 100644
--- a/docs/v2.0/integrations.md
+++ b/docs/v2.0/integrations.md
@@ -6,6 +6,17 @@ Use this page to choose and configure supported CRM/NMS integrations. Use per-in
Most operators use built-in integrations. If you use your own scripts as the source of truth for `network.json` and `ShapedDevices.csv`, start with [Operating Modes and Source of Truth](operating-modes.md).
+```{mermaid}
+flowchart LR
+ A[CRM/NMS] --> B[LibreQoS Integration Job]
+ B --> C[ShapedDevices.csv]
+ B --> D[network.json]
+ C --> E[lqos_scheduler]
+ D --> E
+ E --> F[Shaping Updates]
+ E --> G[WebUI Status / Urgent Issues]
+```
+
## Choose Your Integration Path
| Path | Best fit | Primary source of truth |
@@ -37,11 +48,6 @@ When integrations are enabled:
- `network.json` may also be overwritten depending on integration settings (for example `always_overwrite_network_json`).
- Manual edits may be overwritten on the next refresh cycle.
-## Need Full Legacy Reference?
-
-Detailed legacy integration content is preserved here:
-- [Integration Reference (Detailed)](integrations-reference.md)
-
## Related Pages
- [Quickstart](quickstart.md)
diff --git a/docs/v2.0/lts.md b/docs/v2.0/lts.md
deleted file mode 100644
index 8ab254de..00000000
--- a/docs/v2.0/lts.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Legacy LTS Naming (Deprecated)
-
-```{warning}
-LTS is deprecated and has been superseded by LibreQoS Insight.
-For current deployments and new subscriptions, use Insight docs:
-[Insight](insight.md)
-```
-
-## Migration note
-
-If you have legacy references to LTS in older internal docs/runbooks:
-- Replace them with Insight references.
-- Use [insight.md](insight.md) for current product behavior and workflows.
-- Use [api.md](api.md) for Node API details (`/api-docs` on your node is authoritative).
-- In some UI/code paths, historical names such as `lts_trial` or `config_lts` may still exist; these refer to Insight signup/config flows.
-
-Legacy LTS onboarding instructions have been removed from this guide to avoid confusion for new deployments.
diff --git a/docs/v2.0/node-manager-ui.md b/docs/v2.0/node-manager-ui.md
index 6e78ea89..32dbcf00 100644
--- a/docs/v2.0/node-manager-ui.md
+++ b/docs/v2.0/node-manager-ui.md
@@ -70,7 +70,3 @@ journalctl -u lqosd --since "10 minutes ago"
- [Components](components.md)
- [Configuration](configuration.md)
- [Troubleshooting](troubleshooting.md)
-
-## Legacy Naming Note
-
-Some internal page identifiers can still use historical `lts_*` naming in current builds. In operator terms, these map to Insight functionality.
diff --git a/docs/v2.0/operating-modes.md b/docs/v2.0/operating-modes.md
index befdbcd8..fd61ae85 100644
--- a/docs/v2.0/operating-modes.md
+++ b/docs/v2.0/operating-modes.md
@@ -4,6 +4,18 @@
Use this page to choose and enforce your source-of-truth policy (built-in integrations vs custom source-of-truth) before production changes.
+```{mermaid}
+flowchart TD
+ A[Choose Source of Truth] --> B{Using built-in CRM/NMS integration?}
+ B -->|Yes| C[Built-in Integrations Mode]
+ B -->|No| D{Generating files from your own scripts/systems?}
+ D -->|Yes| E[Custom Source-of-Truth Mode]
+ D -->|No| F[Manual Files Mode]
+ C --> G[Integration sync jobs own file refresh]
+ E --> H[External script pipeline owns persistence]
+ F --> I[Direct file maintenance; best for small networks]
+```
+
LibreQoS supports two first-class operating modes.
## Built-in Integrations (Recommended for Most Operators)
diff --git a/docs/v2.0/quickstart.md b/docs/v2.0/quickstart.md
index 4a74a878..61cd05cf 100644
--- a/docs/v2.0/quickstart.md
+++ b/docs/v2.0/quickstart.md
@@ -2,10 +2,32 @@
Use this page to choose the correct deployment path quickly, then execute only the steps for that path.
+```{mermaid}
+flowchart TD
+ A[Start Here: Quickstart] --> B{Choose Path}
+ B --> C[Testbed / Lab]
+ B --> D[Supported Integration]
+ B --> E[Custom Script Integration]
+ B --> F[Manual Files <100 subscribers]
+ C --> G[Configure + Validate in WebUI]
+ D --> G
+ E --> G
+ F --> G
+ G --> H[Troubleshoot / Optimize / Scale]
+```
+
## Common Install Foundation
Complete this once before any path-specific steps.
+```{mermaid}
+flowchart LR
+ A[Review Design + Requirements] --> B[Host Prerequisites + Ubuntu]
+ B --> C[Configure Bridge]
+ C --> D[Install LibreQoS .deb]
+ D --> E[Open WebUI]
+```
+
1. Review deployment assumptions and capacity:
- [Deployment Scenarios](design.md)
- [System Requirements](requirements.md)
@@ -119,8 +141,3 @@ Recommended only for networks under 100 subscribers.
- [Operating Modes and Source of Truth](operating-modes.md)
- [Scale Planning and Topology Design](scale-topology.md)
- [Troubleshooting](troubleshooting.md)
-
-## Developer Install (Not Recommended for Operators)
-
-Git-based install instructions are here:
-- [Git Install (For Developers)](git-install.md)
diff --git a/docs/v2.0/stormguard.md b/docs/v2.0/stormguard.md
index bf86bfeb..be1739ef 100644
--- a/docs/v2.0/stormguard.md
+++ b/docs/v2.0/stormguard.md
@@ -2,6 +2,10 @@
StormGuard is LibreQoS' adaptive queue-adjustment subsystem for congestion and quality events.
+> **Important Scope Warning**
+> StormGuard is intended for specific use cases, such as controlling congestion on variable-bandwidth WAN links (for example maritime networks), or a small number of access points with highly variable capacity.
+> It is not intended to manage dozens or hundreds of nodes at the same time.
+
## What StormGuard Does
- Monitors real-time signals (throughput, RTT/loss-related metrics, and saturation context).
diff --git a/index.rst b/index.rst
index 0305b476..acc983d0 100644
--- a/index.rst
+++ b/index.rst
@@ -39,7 +39,6 @@ Welcome to the LibreQoS documentation
docs/v2.0/insight
docs/v2.0/api
- docs/v2.0/lts
.. toctree::
:maxdepth: 1
diff --git a/requirements_dev.txt b/requirements_dev.txt
index 9ccec5bd..5838e5f0 100644
--- a/requirements_dev.txt
+++ b/requirements_dev.txt
@@ -1,3 +1,4 @@
sphinx==6.2.1
sphinx_rtd_theme
myst-parser
+sphinxcontrib-mermaid