Entscheidung dieser Sitzung war "bauen statt schliessen". Gebaut ist es. Das
Ergebnis stellt TP6 aber neu: die Queue steht, ist compliant, und tut nichts.
DREI BELEGE AM GERAET, unabhaengig voneinander:
/queue tree nach 6 MB echtem Client-Upload -> 0 Bytes
Simple Queue auf 10.40.0.0/16 (Gegenprobe) -> 0 Bytes
Upload gegen cake-bandwidth=8.5Mbps -> 9,48 Mbit
Der dritte ist der harte. Ein Zaehler auf 0 laesst sich als Anzeigeproblem
wegerklaeren, ein Durchsatz UEBER dem gesetzten Limit nicht.
URSACHE (sehr wahrscheinlich, nicht abschliessend bewiesen): CRS326 mit
Marvell-98DX3236. Bridge faehrt hw-offload, alle Ports only-hardware-queue,
Bridge-Interface no-queue. Der Switch-Chip serialisiert, nicht die CPU. Dass
l3-hw-offloading=no ist, widerspricht dem nicht: die CPU routet (Firewall zaehlt
32,9 Mio Pakete), aber sie serialisiert nicht.
WAS BESTAND HAT -- die ComplianceRule `queue`:
- nautobot/ingest-queue-rule.py (idempotent, Dry-Run default)
- match_config = "/queue type\n/queue tree"; /queue interface bewusst NICHT,
das traegt nur die Default-Portzuordnung und hat mit QoS nichts zu tun
- Wirksamkeit bewiesen, nicht behauptet: erst 99/100 mit exakt der fehlenden
Queue als `missing`, nach dem Deploy 100/100, 0 Drifts
- Zaehler jetzt 25 Rules x 4 Geraete = 100 Checks
Damit ist dieselbe blinde Stelle zu, die TP26 fuer /ip firewall filter geschlossen
hat -- und zwar VOR der Queue, wie Runbook 4.1 es verlangt.
ZWEI DESIGN-ENTSCHEIDUNGEN, die im Template begruendet stehen:
- nur die Senderichtung: der Download liegt mit +23..28 ms UNTER der
3-Schwelle und ist nach demselben Kriterium Fall A
- parent=vlan100 statt target=10.40.0.0/16: eine Simple Queue aufs LAN-Supernetz
haette Inter-VLAN (NAS <-> MAIN, geroutet ueber dieselbe CPU) mitgedrosselt
VIER SACKGASSEN, dokumentiert in ref_crs326_keine_software_queue:
1. active-queue=queue-tree heisst nur "verdrahtet", nicht "wirksam"
2. parent=global OHNE packet-mark faengt per Definition nichts
3. target=0.0.0.0/0 wird stillschweigend zu target="" verworfen
4. router-eigener Verkehr durchlaeuft die Queues nicht -- Test-Pings vom Router
beweisen nichts, es braucht einen echten LAN-Client
Zwei davon sahen wie Hardware-Befunde aus und waren eigene Testfehler.
FORMATFALLE: RouterOS exportiert 8.5Mbps statt 8500000 und schiebt eine eigene
Hinweiszeile vor die Tree-Zeile, wodurch der Backup-Normalisierer /queue tree
nicht abflacht. Template baut beides nach -> 100/100.
Alle Testaenderungen liefen als Config-Transaktion und sind zurueckgebaut; keine
Akte offen. Die wirkungslose Queue bleibt vorerst am Geraet und in der SoT --
dokumentiert, nicht als aktives QoS misszuverstehen -- bis ueber die drei Wege
entschieden ist (hw-offload opfern / Chip-QoS ohne CAKE / TP6 schliessen).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Transaktionen — Teständerungen mit Ablaufdatum
Hier liegen die Akten offener und geschlossener Config-Transaktionen. Werkzeug:
nautobot/gc-transaktion.py.
Wozu
Eine Änderung, die am Gerät steht, aber nicht in der SoT, ist Drift — und Drift sieht bisher immer gleich aus, egal ob er ein Versehen ist oder ein laufender Versuch. Wer testen wollte, hatte die Wahl zwischen „Compliance kaputt" und „gar nicht testen".
Eine Transaktion macht die Absicht sichtbar, ohne die Governance aufzuweichen: der Change geht
weiterhin ausschließlich über Golden Config (gc-manual-plan.py), und die Compliance meldet den
Drift weiterhin. Neu ist nur, dass status ihn zuordnen kann.
| SQL | hier |
|---|---|
BEGIN |
Snapshot des Scope-Abschnitts + Akte mit Gerät, Scope, Grund und Ablaufdatum |
| uncommitted | Change ist am Gerät wirksam und im Testumfeld sichtbar, aber nicht in der SoT |
COMMIT |
Template/Config-Context nachziehen → Compliance grün → Akte schließen |
ROLLBACK |
Rückbau-Vorschlag aus dem Snapshot, prüfen, deployen, Akte schließen |
Drei Regeln, die das Werkzeug erzwingt
--expiresist Pflicht. Eine offene Transaktion ohne Frist ist undokumentierter Drift mit besserem Gewissen.statusmarkiert überfällige Akten.- Der Scope ist eine ComplianceRule, kein Freibrief. Driftet etwas außerhalb des Scopes, meldet
statusdas ausdrücklich als nicht abgedeckt. - Eine offene Transaktion je Gerät — sonst ist beim Rollback nicht mehr entscheidbar, wohin zurück.
Zwei bewusste Grenzen
- Der Rollback pusht nicht selbst. Er schreibt einen Vorschlag aus dem Snapshot;
add-Zeilen aus einem/exportlegen neu an, statt zu ändern, und brauchen meist einset [find …]. Ein Rückbau, den niemand gelesen hat, ist genau die Sorte Automatik, die hier schon zweimal teuer war. - Der Snapshot enthält nur den Scope-Abschnitt. Ein voller
/exportenthält Firewall, Adressen, Benutzerliste und Skriptquellen — nichts davon wird für den Rückbau gebraucht, und diese Akten liegen im Git. Für den Ernstfall gibt es das binäre/system backupauf dem Gerät (--device-backup).
Dateien je Transaktion
| Datei | Inhalt |
|---|---|
<change-id>.json |
die Akte: Gerät, Scope, Grund, Fristen, Status |
<change-id>.snapshot.rsc |
der Scope-Abschnitt vor der Änderung |
<change-id>.commands.rsc |
was deployt wurde |
<change-id>.rollback.rsc |
erst nach rollback — der Vorschlag zum Prüfen |