TP6.1 live: NAS-Sync weicht zurueck -- 40,8 auf 11,0 ms unter Last
Christophs Einwand beim TP6-Abschluss war berechtigt, und er kippt die Erklaerung,
die ich einen Tag lang vertreten habe.
ABNAHME (gleiche NAS-Last, gleicher Messclient, Kontrolle inklusive):
Priorisierung aus 40,8 ms avg / 53,4 max
Priorisierung an 11,0 ms avg / 14,6 max -73 %
Die Last war echt, nicht behauptet: wan-up-total fuhr 9,0 Mbit (max-limit greift
exakt), wan-up-bulk 8,87 Mbit mit 1581 Drops, vlan100 tx 9,0 Mbps. Die Kontrolle
mit abgeschalteter Markierung war noetig, um auszuschliessen, dass die Verbesserung
bloss daher kommt, dass Bulk und Ping jetzt von verschiedenen Hosts stammen.
KORREKTUR AN TP6: dort steht, die 30 ms entstuenden im DOCSIS-Uplink und seien
unabaenderlich. Das ist widerlegt. Der Fehler lag in der METHODE dieser Messung:
Bulk und Messverkehr kamen vom SELBEN Host, also gab es fuer CAKEs triple-isolate
nichts zu trennen -- alles lag in derselben Klasse, und Shapen allein aendert keine
Reihenfolge. Was CAKE nicht schaffte, schafft explizite Klassentrennung.
TP6 traegt jetzt einen Warnhinweis und ist als Messprotokoll zu lesen, nicht als
Ursachenanalyse. Weiter gueltig bleibt: CAKE als EINE Queue ueber allem brachte
nichts (dreimal gemessen), und Interface-HTB ist auf diesem Geraet tot.
GEBAUT (Template [11a], via GC):
2x mangle postrouting (VOR src-nat -- nur dort ist die LAN-Quelle sichtbar):
NAS 10.40.20.10 -> bulkup, alles andere -> restup
wan-up-total (parent=global, max-limit=9M)
wan-up-rest priority=1 limit-at=6M
wan-up-bulk priority=8 limit-at=1M
Drei Entscheidungen, begruendet im Template:
- Prioritaet statt Cap: ein Limit haette die NAS auch nachts gebremst und
Bandbreite verschenkt (DSM drosselt nicht, User-bestaetigt). limit-at=1M
sorgt dafuer, dass der Sync nie ganz verhungert.
- src-address=10.40.20.10, NICHT VLAN20: dort haengen auch HA, Nautobot, pve.
- parent=global, nicht vlan100: Interface-HTB ist hier wirkungslos.
GOVERNANCE: ComplianceRule ip-firewall-mangle angelegt (ingest-mangle-rule.py),
config_ordered=True -- die NAS-Regel muss vor dem Catch-all stehen, sonst waere die
Priorisierung STILL wirkungslos. 26 Rules x 4 Geraete = 104 Checks, 104/104 gruen.
Formatfalle nebenbei: priority=8 ist Default und wird von /export weggelassen --
explizit im Template erzeugt es Dauer-Drift, bei dem das Geraet recht hat.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -421,7 +421,16 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
|||||||
- **(b) Live-Torch als Ad-hoc-Observability:** DNS ist bei direktem 1.1.1.1 blind, **Flows nicht** (NATen über ap1). `torch` auf `vlan30`/`vlan50` gefiltert auf die Geräte-IP zeigt Ziel-IPs live (Versuni → AWS `eu-west-1` IoT erkennbar). Voraussetzung: Gerät aktiv. Merkregel: Airfryer nur online wenn er kocht → Capture ans Einschalten koppeln.
|
- **(b) Live-Torch als Ad-hoc-Observability:** DNS ist bei direktem 1.1.1.1 blind, **Flows nicht** (NATen über ap1). `torch` auf `vlan30`/`vlan50` gefiltert auf die Geräte-IP zeigt Ziel-IPs live (Versuni → AWS `eu-west-1` IoT erkennbar). Voraussetzung: Gerät aktiv. Merkregel: Airfryer nur online wenn er kocht → Capture ans Einschalten koppeln.
|
||||||
- **Abh.:** UNTRUSTED-Move des Airfryers (Kandidat, s. VLAN50) + TP5-Deny-by-default. Kein Blocker.
|
- **Abh.:** UNTRUSTED-Move des Airfryers (Kandidat, s. VLAN50) + TP5-Deny-by-default. Kein Blocker.
|
||||||
|
|
||||||
### TP6 — QoS/CAKE + Call-Quality-A/B-Test ▸ ✅ **GESCHLOSSEN 2026-08-23 — gebaut, gemessen, wieder ausgebaut. CAKE wirkt, reicht aber nicht an die Ursache.**
|
### TP6 — QoS/CAKE + Call-Quality-A/B-Test ▸ ✅ **GESCHLOSSEN 2026-08-23 — CAKE gebaut, gemessen, wieder ausgebaut.** ⚠️ **Die Erklaerung darin ist von TP6.1 ueberholt: nicht DOCSIS, sondern fehlende Klassentrennung.**
|
||||||
|
> 🔴 **ZUERST LESEN — diese Analyse ist teilweise widerlegt (2026-08-23, durch TP6.1).**
|
||||||
|
> Unten steht, die ~30 ms entstuenden im DOCSIS-Uplink und seien unabaenderlich. **Sie sind es
|
||||||
|
> nicht.** TP6.1 holt dieselbe Strecke unter derselben Saettigung auf **11,0 ms** — allein durch
|
||||||
|
> Klassentrennung mit Prioritaet. Der Fehler lag in der **Methode** hier: Bulk und Messverkehr
|
||||||
|
> kamen vom **selben Host**, damit gab es fuer CAKEs `triple-isolate` nichts zu trennen, und
|
||||||
|
> blosses Shapen aendert keine Reihenfolge. **Weiter gueltig bleibt:** dass CAKE als *eine*
|
||||||
|
> Queue ueber allem nichts brachte (dreimal gemessen), und der Befund zur Queue-Platzierung
|
||||||
|
> (Interface-HTB tot, Global-HTB wirkt). Der Rest dieses Abschnitts ist als Messprotokoll zu
|
||||||
|
> lesen, nicht als Ursachenanalyse.
|
||||||
> 🔴 **A/B gemessen, gleicher Client, gleiche Methode, Minuten auseinander:**
|
> 🔴 **A/B gemessen, gleicher Client, gleiche Methode, Minuten auseinander:**
|
||||||
>
|
>
|
||||||
> | Konfiguration | avg Latenz unter Upload-Last |
|
> | Konfiguration | avg Latenz unter Upload-Last |
|
||||||
@@ -549,50 +558,54 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
|||||||
Ohne diese Zahl ist die übliche CAKE-Vorgabe „85–95 % Linerate" geraten.
|
Ohne diese Zahl ist die übliche CAKE-Vorgabe „85–95 % Linerate" geraten.
|
||||||
- **Abh.:** TP5 ✅ (keine Blocker mehr). Vorgelagert: die Messung oben.
|
- **Abh.:** TP5 ✅ (keine Blocker mehr). Vorgelagert: die Messung oben.
|
||||||
|
|
||||||
### TP6.1 — Saettigung vermeiden statt Bufferbloat bekaempfen (Bulk-Uploads zuruecknehmen) ▸ 🟠 **VORSCHLAG 2026-08-23, aus dem TP6-Abschluss heraus**
|
### TP6.1 — Saettigung vermeiden statt Bufferbloat bekaempfen ▸ ✅ **LIVE UND GEMESSEN (2026-08-23): 40,8 → 11,0 ms unter Last**
|
||||||
> **Der Gedanke kommt von Christoph** („dann koennten wir zumindest den Sync von der NAS
|
> **Der Gedanke kam von Christoph** beim TP6-Abschluss („dann koennten wir zumindest den Sync
|
||||||
> zurueckhalten“) und er trifft eine Luecke im TP6-Urteil. TP6 hat gezeigt: die ~30 ms
|
> von der NAS zurueckhalten“) — und er hat mein TP6-Urteil zu Recht angezweifelt.
|
||||||
> Zusatzlatenz sind **nicht** wegzushapen, weil sie im DOCSIS-Uplink entstehen. Aber sie
|
|
||||||
> treten **nur unter Saettigung** auf — im Leerlauf misst dieselbe Strecke **12,9 ms**.
|
|
||||||
>
|
>
|
||||||
> ⚖️ **Damit ist das Ziel ein anderes: nicht die Latenz unter Last senken, sondern die Last
|
> 🟢 **Abnahme, echte Saettigung, Kontrollmessung inklusive:**
|
||||||
> gar nicht erst entstehen lassen.** Ein NAS-Sync, der bei laufendem Call zurueckweicht,
|
|
||||||
> haelt die Leitung aus der Saettigung — und dann liegt der Call bei 12,9 statt 42 ms. Das
|
|
||||||
> ist die Verbesserung, die CAKE nicht liefern konnte, und sie ist **groesser** als alles, was
|
|
||||||
> Bufferbloat-Bekaempfung hier je gebracht haette.
|
|
||||||
>
|
>
|
||||||
> ✅ **Die Vorarbeit ist erledigt und bewiesen** (TP6): der **Global-HTB-Weg funktioniert** auf
|
> | gleiche NAS-Last, gleicher Messclient | avg | max |
|
||||||
> diesem Geraet — `mangle chain=postrouting out-interface=vlan100 action=mark-packet` plus
|
> |---|---|---|
|
||||||
> `/queue tree parent=global packet-mark=…`. Gemessen: zaehlt 6 MB, drosselt 9,3 → 7,78 Mbit.
|
> | Priorisierung **aus** | **40,8 ms** | 53,4 ms |
|
||||||
> Der Interface-Weg (`parent=<interface>`) ist dagegen tot, s. TP6.
|
> | Priorisierung **an** | **11,0 ms** | 14,6 ms |
|
||||||
>
|
>
|
||||||
> **Entwurf (zu bauen, nicht gebaut):** ein Parent-Tree mit `max-limit` knapp unter der
|
> **−73 %.** Und die Last war echt, nicht behauptet: `wan-up-total` fuhr **9,0 Mbit**
|
||||||
> Linerate — nur so muss HTB ueberhaupt entscheiden — und darunter zwei Klassen:
|
> (das max-limit greift exakt), `wan-up-bulk` 8,87 Mbit mit **1581 Drops** — der Sync wurde
|
||||||
> - `priority=8` **Bulk**: Upload **von der NAS** (`src-address=10.40.20.10`). Bewusst die
|
> aktiv gebremst, waehrend `wan-up-rest` frei durchlief. `vlan100 tx = 9,0 Mbps`.
|
||||||
> Host-IP, **nicht** ganz VLAN20 — dort haengen auch HA, Nautobot und pve, die nicht
|
> Die Kontrolle mit abgeschalteter Markierung war noetig, um auszuschliessen, dass die
|
||||||
> pauschal hinten anstehen sollen.
|
> Verbesserung bloss daher kommt, dass Bulk und Ping jetzt von verschiedenen Hosts stammen.
|
||||||
> - `priority=1` **Rest**: alles andere, insbesondere Calls.
|
|
||||||
>
|
>
|
||||||
> 🔴 **Priorisierung, kein hartes Limit.** Ein festes Cap wuerde den Sync auch dann bremsen,
|
> 🔴 **Damit ist die DOCSIS-Erklaerung aus TP6 widerlegt.** Dort stand, die ~30 ms
|
||||||
> wenn die Leitung frei ist. Prioritaet nimmt ihm die Bandbreite nur, solange jemand anders
|
> entstuenden stromabwaerts im Uplink und seien unabaenderlich. Sie sind es nicht — sie
|
||||||
> sie braucht — das ist genau die Bedingung, unter der es hier ueberhaupt weh tut.
|
> loesen sich auf, sobald der Verkehr in **getrennte Klassen** faellt. Der Fehler steckte in
|
||||||
|
> der TP6-**Methode**: Bulk und Messverkehr kamen vom **selben Host**, also gab es fuer CAKEs
|
||||||
|
> Host-Fairness (`triple-isolate`) nichts zu trennen — alles lag in derselben Klasse, und
|
||||||
|
> Shapen allein aendert an einer Reihenfolge nichts. Was CAKE nicht schaffte, schafft
|
||||||
|
> **explizite Klassentrennung mit Prioritaet**. Merkregel: nicht die Bandbreite ist das
|
||||||
|
> Problem, sondern **wer vor wem drankommt**.
|
||||||
>
|
>
|
||||||
> **Preis, ehrlich:** der Parent muss unter die Linerate shapen (~1 Mbit Spitze weniger,
|
> **Was gebaut ist** (Template [11a], via GC, 104/104 compliant):
|
||||||
> derselbe Preis wie bei CAKE), und Mangle kostet CPU pro Paket — bei 9,6 Mbit WAN irrelevant.
|
> - zwei `mangle`-Regeln in `postrouting` (**vor** src-nat — nur dort ist die LAN-Quelle noch
|
||||||
|
> sichtbar): NAS → `bulkup`, alles andere → `restup`
|
||||||
|
> - `wan-up-total` (`parent=global`, `max-limit=9M`) mit zwei Klassen darunter:
|
||||||
|
> `wan-up-rest` `priority=1 limit-at=6M` und `wan-up-bulk` `priority=8 limit-at=1M`
|
||||||
>
|
>
|
||||||
> 🔴 **Governance-Vorbedingung, dieselbe wie bei TP6:** `/ip firewall mangle` steht unter
|
> **Drei Entscheidungen, die begruendet bleiben sollen:**
|
||||||
> **keiner ComplianceRule**. Die Regeln waeren also unsichtbarer Drift. Vor dem Bau eine Rule
|
> 1. **Prioritaet statt hartem Cap** — ein Limit haette die NAS auch nachts gebremst und
|
||||||
> `ip-firewall-mangle` anlegen — Muster liegt mit `nautobot/ingest-queue-rule.py` vor. Die
|
> Bandbreite verschenkt (DSM drosselt von sich aus nicht, User-bestaetigt 2026-08-23).
|
||||||
> Rule `queue` existiert bereits und deckt den Tree-Teil ab.
|
> `limit-at=1M` sorgt dafuer, dass der Sync nie ganz verhungert.
|
||||||
|
> 2. **`src-address=10.40.20.10`, nicht VLAN20** — in INFRA haengen auch HA, Nautobot und
|
||||||
|
> pve. Wer das je auf `10.40.20.0/24` erweitert, verlangsamt seine eigenen Werkzeuge.
|
||||||
|
> 3. **`parent=global`, nicht `parent=vlan100`** — Interface-HTB ist auf diesem Geraet tot
|
||||||
|
> (hw-offloadetes out-interface, s. TP6).
|
||||||
>
|
>
|
||||||
> 🔴 **Abnahme misst den Call, nicht die Queue:** Ping-Latenz waehrend eines echten
|
> ✅ **Governance-Vorbedingung erfuellt:** ComplianceRule **`ip-firewall-mangle`** angelegt
|
||||||
> NAS-Syncs, gegen die 12,9 ms idle. Ein Queue-Zaehler beweist hier gar nichts — genau der
|
> (`nautobot/ingest-mangle-rule.py`), **`config_ordered=True`** — die NAS-Regel muss vor dem
|
||||||
> Fehler, der in TP6 eine Nacht gekostet hat (`feedback_abnahme_wirkung_nicht_anzeige`).
|
> Catch-all stehen, sonst waere die Priorisierung **still** wirkungslos. Zaehler jetzt
|
||||||
> **Vorher pruefen, ob der Fall ueberhaupt auftritt:** laeuft der Synology-Sync tatsaechlich
|
> **26 Rules x 4 Geraeten = 104 Checks**.
|
||||||
> ins offene Messer, oder drosselt DSM ihn ohnehin schon? Ohne diesen Nachweis waere TP6.1
|
|
||||||
> eine Loesung auf Verdacht — und davon hatte TP6 genug.
|
|
||||||
>
|
>
|
||||||
> **Abh.:** keine harten. Erbt die Erkenntnisse aus TP6; blockiert nichts.
|
> 💡 **Offen, klein:** ob weitere Bulk-Quellen dazugehoeren (pve-Backups? Time Machine?).
|
||||||
|
> Erst messen, ob sie ueberhaupt saettigen — die Regel dafuer ist eine Zeile.
|
||||||
|
|
||||||
### TP7 — Media-Discovery (mDNS) für VLAN 40 ▸ ✅ FERTIG (2026-07-02) — `docs/tp7-mdns.md`
|
### TP7 — Media-Discovery (mDNS) für VLAN 40 ▸ ✅ FERTIG (2026-07-02) — `docs/tp7-mdns.md`
|
||||||
- ✅ **Built-in mDNS-Repeater** aktiv — **Live-Stand `crs326-core` (verifiziert 2026-08-14):**
|
- ✅ **Built-in mDNS-Repeater** aktiv — **Live-Stand `crs326-core` (verifiziert 2026-08-14):**
|
||||||
@@ -2120,9 +2133,8 @@ den Weg, über den man den Fehler zurücknehmen wollte.
|
|||||||
Datenpfad (im TP5-Log mit 137 Zeilen belegt); Container braucht nur noch der **öffentliche** Ingress.
|
Datenpfad (im TP5-Log mit 137 Zeilen belegt); Container braucht nur noch der **öffentliche** Ingress.
|
||||||
Vorschlag: `nautobot` als Probe aus dem CF-Ingress nehmen.
|
Vorschlag: `nautobot` als Probe aus dem CF-Ingress nehmen.
|
||||||
- ~~**DoH-Cloudflare auf `crs326-core`**~~ ✅ **erledigt 2026-08-18** (TP23 Stufe 1 = TP21.1 TODO 1).
|
- ~~**DoH-Cloudflare auf `crs326-core`**~~ ✅ **erledigt 2026-08-18** (TP23 Stufe 1 = TP21.1 TODO 1).
|
||||||
- **TP6.1 — Saettigung vermeiden (NEU 2026-08-23):** NAS-Sync per Prioritaet zuruecknehmen,
|
- ~~**TP6.1 — Saettigung vermeiden**~~ ✅ **LIVE 2026-08-23: 40,8 → 11,0 ms unter Last** (−73 %).
|
||||||
damit ein Call gar nicht erst in die Saettigung geraet (12,9 statt 42 ms). Vorarbeit aus TP6
|
NAS-Sync weicht bei Last zurueck, ComplianceRule `ip-firewall-mangle` angelegt, 104/104.
|
||||||
ist bewiesen; Vorbedingung ist eine ComplianceRule fuer `/ip firewall mangle`.
|
|
||||||
- **TP24 — DC-USV** (seit 2026-08-16 eigener TP, aus TP15 herausgelöst).
|
- **TP24 — DC-USV** (seit 2026-08-16 eigener TP, aus TP15 herausgelöst).
|
||||||
- ~~**TP19 — VLAN1-Client-Retirement / cudy-Teardown**~~ ✅ **geschlossen 2026-08-18** (VLAN1-ARP = 0). Die zwei Reste sind dorthin verschoben, wo sie hingehören: tote CF-Tunnel → TP16, HA-Portainer `setup_retry` → TP11.
|
- ~~**TP19 — VLAN1-Client-Retirement / cudy-Teardown**~~ ✅ **geschlossen 2026-08-18** (VLAN1-ARP = 0). Die zwei Reste sind dorthin verschoben, wo sie hingehören: tote CF-Tunnel → TP16, HA-Portainer `setup_retry` → TP11.
|
||||||
- ~~**TP3.3 — WLAN-Coverage-Kur**~~ → **in TP25 aufgegangen** (2026-08-17). 802.11k/v ist repariert (08-13);
|
- ~~**TP3.3 — WLAN-Coverage-Kur**~~ → **in TP25 aufgegangen** (2026-08-17). 802.11k/v ist repariert (08-13);
|
||||||
@@ -2157,7 +2169,7 @@ steht unten unter „Durch". Nachfolger ist **TP16.3**, das oben unter Follow-up
|
|||||||
|
|
||||||
TP1 · TP2 · TP2.1 · TP3 (Rebuild 2026-08-08) · TP3.1 · TP4 (Rolle seit 08-08 auf dem Core) · TP7 · TP7.2 ·
|
TP1 · TP2 · TP2.1 · TP3 (Rebuild 2026-08-08) · TP3.1 · TP4 (Rolle seit 08-08 auf dem Core) · TP7 · TP7.2 ·
|
||||||
TP10 (Kern) · TP14 (+14.1/14.2/14.2a/14.3/14.5) · TP15 · TP16 (Kern) · TP17 · TP19.1 · TP20 · TP21 · TP21.1 ·
|
TP10 (Kern) · TP14 (+14.1/14.2/14.2a/14.3/14.5) · TP15 · TP16 (Kern) · TP17 · TP19.1 · TP20 · TP21 · TP21.1 ·
|
||||||
TP22 · TP-R · **TP3.2** (08-17) · **TP5** (08-18) · **TP7.1** (08-18) · **TP19** (08-18) · **TP23 Stufe 1** (08-18) · **TP6** (08-23, geschlossen statt gebaut) · **TP26** (08-17) · **TP27** (08-17/18) · **TP28** (08-17, GC-Modell 08-18). **Verworfen:** TP9 (Gateway-HA, User-Entscheid 2026-08-08). **Obsolet:** Omada-PVID-Fix
|
TP22 · TP-R · **TP3.2** (08-17) · **TP5** (08-18) · **TP7.1** (08-18) · **TP19** (08-18) · **TP23 Stufe 1** (08-18) · **TP6** (08-23, geschlossen statt gebaut) · **TP6.1** (08-23, Upload-Prio live) · **TP26** (08-17) · **TP27** (08-17/18) · **TP28** (08-17, GC-Modell 08-18). **Verworfen:** TP9 (Gateway-HA, User-Entscheid 2026-08-08). **Obsolet:** Omada-PVID-Fix
|
||||||
(User-Entscheid 2026-07-22 — „nie wieder aufgreifen").
|
(User-Entscheid 2026-07-22 — „nie wieder aufgreifen").
|
||||||
|
|
||||||
<details><summary>📜 Historische Fassung dieses Abschnitts (bis 2026-08-14 fortgeschrieben, hier bewusst erhalten)</summary>
|
<details><summary>📜 Historische Fassung dieses Abschnitts (bis 2026-08-14 fortgeschrieben, hier bewusst erhalten)</summary>
|
||||||
|
|||||||
122
nautobot/ingest-mangle-rule.py
Executable file
122
nautobot/ingest-mangle-rule.py
Executable file
@@ -0,0 +1,122 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
ComplianceRule `ip-firewall-mangle` anlegen (idempotent).
|
||||||
|
|
||||||
|
Die Luecke, die das schliesst
|
||||||
|
-----------------------------
|
||||||
|
`/ip firewall mangle` stand unter **keiner** ComplianceRule. Fuer TP6.1 ist das nicht
|
||||||
|
egal, sondern zentral: die Upload-Priorisierung besteht aus **zwei** Teilen, und der
|
||||||
|
Queue-Tree allein ist wirkungslos. Faellt die Markierungsregel weg oder driftet sie,
|
||||||
|
landet aller Verkehr in derselben Klasse -- und **nichts** meldet das, waehrend die
|
||||||
|
Queue weiter zufrieden aussieht.
|
||||||
|
|
||||||
|
Dieselbe blinde Stelle, die TP26 fuer `/ip firewall filter` und TP6 fuer `/queue`
|
||||||
|
geschlossen hat.
|
||||||
|
|
||||||
|
⚠️ `config_ordered=True`, anders als bei `queue`: Mangle ist eine Kette, die von oben
|
||||||
|
nach unten ausgewertet wird. Die spezifische NAS-Regel MUSS vor dem Catch-all stehen --
|
||||||
|
sonst bekaeme der Sync die Rest-Prioritaet und die ganze Konstruktion waere still
|
||||||
|
wirkungslos. Genau wie bei `ip-firewall-filter`.
|
||||||
|
|
||||||
|
export NAUTOBOT_TOKEN=... # aus docs/nas-vlan20/stacks/210-nautobot.yml
|
||||||
|
python3 nautobot/ingest-mangle-rule.py # Dry-Run
|
||||||
|
python3 nautobot/ingest-mangle-rule.py --apply
|
||||||
|
"""
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import urllib.error
|
||||||
|
import urllib.parse
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
BASE = "http://10.40.20.30:8080/api"
|
||||||
|
TOKEN = os.environ.get("NAUTOBOT_TOKEN", "")
|
||||||
|
APPLY = "--apply" in sys.argv
|
||||||
|
|
||||||
|
FEATURE = "ip-firewall-mangle"
|
||||||
|
BESCHREIBUNG = ("TP6.1: packet-marks fuer die Upload-Priorisierung. Ohne Rule waere die "
|
||||||
|
"Markierung unsichtbarer Drift -- und ohne sie ist der Queue-Tree wirkungslos.")
|
||||||
|
MATCH = "/ip firewall mangle"
|
||||||
|
PLATTFORM = "RouterOS"
|
||||||
|
|
||||||
|
|
||||||
|
def req(method, path, data=None):
|
||||||
|
url = path if path.startswith("http") else BASE + path
|
||||||
|
body = json.dumps(data).encode() if data is not None else None
|
||||||
|
r = urllib.request.Request(url, data=body, method=method)
|
||||||
|
r.add_header("Authorization", "Token " + TOKEN)
|
||||||
|
r.add_header("Content-Type", "application/json")
|
||||||
|
r.add_header("Accept", "application/json")
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen(r, timeout=60) as resp:
|
||||||
|
raw = resp.read()
|
||||||
|
return json.loads(raw) if raw else {}
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
# 🔴 Fehlerkoerper ausgeben: Nautobot begruendet 400er praezise, und ohne den
|
||||||
|
# Text raet man an Feldnamen herum (TP22-Erfahrung).
|
||||||
|
sys.exit("!! %s %s -> %s\n %s" % (method, url, e.code, e.read().decode()[:600]))
|
||||||
|
|
||||||
|
|
||||||
|
def eins(pfad, **filter):
|
||||||
|
q = urllib.parse.urlencode(filter)
|
||||||
|
res = req("GET", "%s?%s" % (pfad, q)).get("results", [])
|
||||||
|
if len(res) > 1:
|
||||||
|
sys.exit("FEHLER: %s?%s liefert %d Treffer, erwartet 0 oder 1" % (pfad, q, len(res)))
|
||||||
|
return res[0] if res else None
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if not TOKEN:
|
||||||
|
sys.exit("NAUTOBOT_TOKEN fehlt.")
|
||||||
|
print("Modus:", "APPLY" if APPLY else "DRY-RUN (nichts wird geschrieben)")
|
||||||
|
|
||||||
|
plat = eins("/dcim/platforms/", name=PLATTFORM)
|
||||||
|
if not plat:
|
||||||
|
sys.exit("Plattform %r nicht gefunden." % PLATTFORM)
|
||||||
|
print("Plattform : %s (%s)" % (plat["display"], plat["id"]))
|
||||||
|
|
||||||
|
feat = eins("/plugins/golden-config/compliance-feature/", name=FEATURE)
|
||||||
|
if feat:
|
||||||
|
print("Feature : existiert bereits (%s)" % feat["id"])
|
||||||
|
else:
|
||||||
|
print("Feature : anlegen -> %s" % FEATURE)
|
||||||
|
if APPLY:
|
||||||
|
feat = req("POST", "/plugins/golden-config/compliance-feature/",
|
||||||
|
{"name": FEATURE, "slug": FEATURE, "description": BESCHREIBUNG})
|
||||||
|
print(" angelegt (%s)" % feat["id"])
|
||||||
|
|
||||||
|
if not feat:
|
||||||
|
print("\nDry-Run: ohne Feature kann die Rule nicht geprueft werden. Mit --apply erneut.")
|
||||||
|
return
|
||||||
|
|
||||||
|
rule = eins("/plugins/golden-config/compliance-rule/",
|
||||||
|
feature=feat["id"], platform=plat["id"])
|
||||||
|
if rule:
|
||||||
|
print("Rule : existiert bereits (%s), match_config=%r"
|
||||||
|
% (rule["id"], rule.get("match_config")))
|
||||||
|
if rule.get("match_config") != MATCH:
|
||||||
|
print(" ⚠️ match_config weicht ab -- erwartet %r" % MATCH)
|
||||||
|
return
|
||||||
|
|
||||||
|
nutzlast = {
|
||||||
|
"feature": feat["id"],
|
||||||
|
"platform": plat["id"],
|
||||||
|
"description": BESCHREIBUNG,
|
||||||
|
# Reihenfolge ist SEMANTISCH: die spezifische NAS-Regel muss vor dem
|
||||||
|
# Catch-all stehen, sonst ist die Priorisierung still wirkungslos.
|
||||||
|
"config_ordered": True,
|
||||||
|
"config_type": "cli",
|
||||||
|
"match_config": MATCH,
|
||||||
|
"custom_compliance": False,
|
||||||
|
"config_remediation": False,
|
||||||
|
}
|
||||||
|
print("Rule : anlegen -> %s auf %s, match_config=%r" % (FEATURE, PLATTFORM, MATCH))
|
||||||
|
if APPLY:
|
||||||
|
r = req("POST", "/plugins/golden-config/compliance-rule/", nutzlast)
|
||||||
|
print(" angelegt (%s)" % r["id"])
|
||||||
|
else:
|
||||||
|
print(" Nutzlast: %s" % json.dumps(nutzlast))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -312,7 +312,46 @@
|
|||||||
# ⚖️ Was hier sehr wohl ginge und offen ist: nicht Bufferbloat bekaempfen, sondern
|
# ⚖️ Was hier sehr wohl ginge und offen ist: nicht Bufferbloat bekaempfen, sondern
|
||||||
# Saettigung VERMEIDEN (Bulk-Uploads zuruecknehmen, damit ein Call gar nicht erst in
|
# Saettigung VERMEIDEN (Bulk-Uploads zuruecknehmen, damit ein Call gar nicht erst in
|
||||||
# die Saettigung geraet). Das ist ein anderes Ziel und steht als TP6.1.
|
# die Saettigung geraet). Das ist ein anderes Ziel und steht als TP6.1.
|
||||||
# Die ComplianceRule `queue` BLEIBT — sie bewacht diesen Abschnitt weiter als leer.
|
# Die ComplianceRule `queue` bewacht diesen Abschnitt weiter — jetzt mit dem Inhalt aus [11a].
|
||||||
|
|
||||||
|
# [11a] UPLOAD-PRIORISIERUNG (TP6.1, 2026-08-23) — das, was TP6 NICHT konnte.
|
||||||
|
#
|
||||||
|
# Der Unterschied in einem Satz: TP6 wollte das Warten ertraeglicher machen und
|
||||||
|
# scheiterte am DOCSIS-Puffer. Das hier verhindert, dass ueberhaupt gewartet wird.
|
||||||
|
# Die 42 ms treten NUR unter Saettigung auf — im Leerlauf misst dieselbe Strecke
|
||||||
|
# 12,9 ms. Ein NAS-Sync, der bei Last zurueckweicht, haelt die Leitung da raus.
|
||||||
|
#
|
||||||
|
# 🔴 PRIORITAET, KEIN CAP. Ein festes Limit fuer die NAS wuerde sie auch nachts
|
||||||
|
# bremsen, wenn die Leitung leer ist — genau die ungenutzte Bandbreite, die
|
||||||
|
# Christoph zu Recht nicht will (DSM drosselt von sich aus nicht). HTB nimmt dem
|
||||||
|
# Bulk die Bandbreite nur, solange jemand anders sie braucht.
|
||||||
|
#
|
||||||
|
# 🔴 `src-address=10.40.20.10` — die NAS-HOST-IP, bewusst NICHT ganz VLAN20.
|
||||||
|
# In INFRA haengen auch HA, Nautobot und pve; die gehoeren nicht pauschal nach
|
||||||
|
# hinten. Wer das je auf 10.40.20.0/24 erweitert, verlangsamt seine Werkzeuge.
|
||||||
|
#
|
||||||
|
# 🔴 `parent=global`, NICHT `parent=vlan100`. Interface-HTB ist auf diesem Geraet
|
||||||
|
# wirkungslos (hw-offloadetes out-interface, s. [11]). Der Global-Weg ist in TP6
|
||||||
|
# als wirksam BEWIESEN: 9,3 -> 7,78 Mbit bei gesetztem Limit.
|
||||||
|
#
|
||||||
|
# ⚠️ Die Markierung MUSS im postrouting stehen und die NAS-Regel VOR dem Catch-all:
|
||||||
|
# mangle postrouting laeuft VOR src-nat, nur dort ist die LAN-Quelle noch sichtbar
|
||||||
|
# (nach dem Masquerade ist alles die WAN-IP). Deshalb steht `ip-firewall-mangle`
|
||||||
|
# auf `config_ordered` — eine vertauschte Reihenfolge waere STILL wirkungslos.
|
||||||
|
#
|
||||||
|
# max-limit=9M auf dem Parent: knapp unter der gemessenen Linerate von 9,6 Mbit.
|
||||||
|
# HTB kann nur verteilen, was es selbst begrenzt — ohne dieses Limit gibt es keine
|
||||||
|
# Knappheit zu priorisieren. Preis: ~0,6 Mbit Spitze.
|
||||||
|
# limit-at sind Garantien, keine Grenzen: der Sync verhungert nie ganz (1M), und
|
||||||
|
# der Rest hat 6M sicher, auch wenn der Sync laeuft.
|
||||||
|
/ip firewall mangle add action=mark-packet chain=postrouting comment="TP6.1: NAS-Bulk" new-packet-mark=bulkup out-interface=vlan100 passthrough=no src-address=10.40.20.10
|
||||||
|
/ip firewall mangle add action=mark-packet chain=postrouting comment="TP6.1: Rest (interaktiv)" new-packet-mark=restup out-interface=vlan100 passthrough=no
|
||||||
|
/queue tree add max-limit=9M name=wan-up-total parent=global
|
||||||
|
/queue tree add limit-at=6M max-limit=9M name=wan-up-rest packet-mark=restup parent=wan-up-total priority=1
|
||||||
|
# ⚠️ Bei wan-up-bulk steht KEIN priority=8, obwohl genau das gemeint ist: 8 ist der
|
||||||
|
# Default, und /export laesst Defaults weg. Ein explizites priority=8 im Template
|
||||||
|
# erzeugt deshalb einen Dauer-Drift, bei dem das Geraet recht hat.
|
||||||
|
/queue tree add limit-at=1M max-limit=9M name=wan-up-bulk packet-mark=bulkup parent=wan-up-total
|
||||||
{% elif obj.role.name == "Switch" %}
|
{% elif obj.role.name == "Switch" %}
|
||||||
# =====================================================================================
|
# =====================================================================================
|
||||||
# L2-Switch (crs326-branch) — Sollzustand des Mgmt-Layers.
|
# L2-Switch (crs326-branch) — Sollzustand des Mgmt-Layers.
|
||||||
|
|||||||
Reference in New Issue
Block a user