Files
bf-infra/docs/call-quality-diagnosis.md

221 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Call-Quality-Diagnose & Handoff — Christoph ↔ Geli Video-Calls
> **Zweck:** Self-contained Übergabe an eine separate Session. Enthält Symptom, **was bereits
> ausgeschlossen ist (mit Messdaten + zwei natürlichen Kontrollexperimenten)**, die leitende
> Hypothese und den Ausführungsplan.
> Stand: 2026-06-16 (**revidiert** nach Anamnese mit Christoph). Ursprünglich im Rahmen von „TP6"
> entstanden, das sich als **Nicht-QoS-Problem** entpuppt hat.
---
## TL;DR
**Video-Calls zwischen Christoph und Geli** (Telegram u.a.) ruckeln/droppen, **andere Calls nicht**.
Die zuerst vermutete **WLAN-Roaming-These ist auf Nebenfaktor herabgestuft.** Zwei natürliche
Kontrollexperimente verschieben den Verdacht klar auf die **Geli-seitige ISP-Strecke**:
- Christophs **nationale** Videocalls (vor Geli) liefen sauber → seine lokale Seite ist *nicht* die Wurzel.
- Geli wechselte **Cable/DSL → Fiber** (jetzt FB 5530 Fiber) → Problem **bleibt** → ihre Last-Mile-Bandbreite ist *nicht* die Wurzel.
→ **Leitende Hypothese:** Hochbitratiges Echtzeit-Video über die **AT↔Geli-Strecke** (kleiner Dorf-ISP
`on-isp.net` / AS202245 Geroldsgrün, **CGNAT**, vermutlich dünnes/abends überlastetes Auslands-Peering)
kippt unter schwer komprimierbarem Bild (**Gegenlicht/Dunkel → Bitraten-Spike**) in Loss/Jitter und
lässt die **Congestion-Control kollabieren**. Roaming/Handover ist additiver Nebenfaktor.
---
## Symptom (vollständig)
- Betroffen: **Christoph ↔ Geli**, **mehrere Messenger** (Telegram u.a.) → **nicht app-spezifisch**.
- **Geli-Calls = 99 % Video.** Christophs **nationale Videocalls vor Geli liefen problemlos** (gleicher
Upload, gleiches WLAN, gleiche Kamera). → starkes Kontrollexperiment für „nicht Christophs Seite".
- **Asymmetrie (Schlüssel):** Christoph ↔ andere = gut; Christoph ↔ Geli = schlecht. (Geli ↔ ihre
deutschen Freunde laut früherer Aussage ebenfalls gut.)
- **Licht-Abhängigkeit (Schlüssel):** Gehäuft bei **Dunkelheit**; **Gegenlicht bei Geli** (helles
Fenster, dunkler Rest) erzeugt sichtbare **Artefakte** auch tagsüber. → zeigt auf **Video-Bitrate**
(Sensorrauschen/Kontrast schwer komprimierbar), nicht auf Bewegung.
- **Bewegung** verschlechtert zusätzlich; **still sitzen = etwas besser, aber weiter mies**.
- **Congestion-Signatur:** **Neuer Call = schlagartig besser, dann „nächster Abbruch vorprogrammiert"**;
**Kamera aus/ein hilft**, solange es „noch nicht zu arg" ist. → klassisch **bandbreiten-/ratengebunden**
mit kollabierendem Bitraten-Schätzer, **nicht** sauberer Pfad mit zufälligem Paketverlust.
- **Jitter-/Burst-Signatur (neu, Schlüssel):** Stille **und/oder Standbild**, **verzerrter Ton („wie E-Gitarre")**,
danach **Turbo-Aufholen der letzten Gesprächsfetzen**. → Pakete werden **nicht nur verloren, sondern in
einem Buffer verzögert und stoßweise nachgeliefert** (Jitter/Queuing/Bufferbloat auf der Strecke).
E-Gitarre = Packet-Loss-Concealment des Codecs; Turbo-Catch-up = verspätet im Pulk angekommene Pakete.
- **Richtung GEKLÄRT (neu):** **Christoph hört/sieht Geli deutlich schlechter; Geli hat es mit Christoph seltener.**
→ dominanter Engpass = **Geli→Christoph**, also **Gelis Senderichtung (Upload)**.
- **WLAN-Korrelat bei Geli (neu):** schlechter mit **Distanz zum AP** und an **schlecht ausgeleuchteten Ecken** —
konkret **draußen auf der Bank an der dicken Hausmauer** (weit/abgeschirmt + dunkel = WLAN-Uplink *und* Bitrate gestresst).
- **WLAN-Architektur ist NICHT das Problem (neu, wichtig gegen Fehlfix):** Coverage gut, **keine Nachbar-WLANs**,
TX 100 %, Dual-Band. Der Engpass ist **nicht Design/Abdeckung**, sondern **Timing auf dem Uplink**:
(a) **Halb-Duplex/Airtime-Contention** (nur einer funkt zugleich; fallweise durch andere aktive Geräte, PS meist aus) → Jitter;
(b) **Retransmits** bei Distanz/Mauer/Bewegung → verspätet-im-Pulk = Jitter (Durchsatz sieht „ok" aus);
(c) **TX 100 % hilft nur Downstream** (AP→Handy) — der **Handy-Uplink** (Gelis ausgehendes Video) bleibt schwach,
v. a. hinter der dicken Mauer; (d) abgelesene **RSSI = Momentaufnahme**, verdeckt kurze **Spikes/Einbrüche**.
- **„Seit Fiber generell schlechter" (Geli, subjektiv) — Confound (neu):** mit dem Fiber-Umbau zog der Router um.
Die **PlayStation** (per WLAN, **aber regulär ausgeschaltet** → kein laufender Call-Contention-Faktor) hat **beim
Gaming Aussetzer** → bleibt als **Indiz für WLAN-Schwachstellen** an ihrem Standort, nicht als Dauer-Ursache.
„Fiber schlechter" = der **Umbau/Router-Standort**, nicht die Leitung.
- **Geräte-unabhängig (neu):** Geli Galaxy Note 10+ (test: A35), Christoph früher S22 → jetzt iPhone 16 Pro —
Problem über alle Wechsel hinweg → **nicht gerätespezifisch**.
- **„Nie das Bandbreitenlimit gesehen" (Christoph) — Mess-Caveat (neu):** FB-Charts zeigen **gemittelte (Mean-)Werte**;
die tödlichen **Sub-Sekunden-Microbursts** (Video-Spikes, WLAN-Retransmits) tauchen darin **nie** auf →
**kein Freispruch** für transiente Sättigung.
### Hardware-Timeline (beide Seiten, identische WLAN-Idee)
- **Christoph:** FB 6660 + 1 Repeater (OG, LAN-„Mesh") → **2× Cudy (2×2)**. ISP = Liwest (DOCSIS), Upload ~10 Mbit.
- **Geli:** FB 6660 + FRITZ-Repeater → Cudy → *(Glasfaser-Umstellung)* → **FB 5530 Fiber + Cudy**.
**APs = Cudy WR3600E** (Wi-Fi 6, Dual-Band 2.4+5 GHz), **TX 100 %**. ISP über alle Epochen konstant =
**`on-isp.net` / AS202245 Geroldsgrün**.
- **Gelis Anschluss (FB-5530-Settings, 2026-06-16):** **2.5↓ / 1.3↑ Gbit** (Bandbreite endgültig kein Faktor).
**IPv4 = CGNAT bestätigt:** WAN-IP `100.72.62.31` ∈ **100.64.0.0/10** (RFC 6598), außen `94.154.138.11`.
**IPv6 = nativ öffentlich:** Prefix `2a0e:7a02:31c:3000::/56`, **kein CGNAT auf v6** (Prefix rotiert ~30 h → DDNS nötig).
DNS = Quad9 (`2620:fe::fe:11`) + ISP-EDNS0 (`37.60.7.2`).
- **Christophs IPv6-Stand (Stand 2026-06-16, korrigiert):** **Liwest bietet KEIN natives IPv6** (techn. Support bestätigt).
Die **FritzBox macht 6to4** und annonciert ein **2002::-Prefix per RA ins VLAN1** → der **FB-nahe VLAN1-Host** hat damit
**(flatterhaftes) 6to4-v6**: `curl -6` zu ifconfig.co klappt (`2002:5638:c211:…`, eingeb. v4 86.56.194.17), aber
**`ping6` Google v6 = 100 % Loss** (Google-6to4-Relays abgeschaltet) = klassische 6to4-Teilerreichbarkeit.
**Intern NICHT durchgereicht:** Mac mini (VLAN20 hinter **ap1**) hat **kein v6** — ap1 macht **kein RA/DHCPv6-PD** auf den
VLANs (TP4 v4-only), **Branch-Switch (Omada) nicht v6-konfiguriert**, **Core-Switch (ALLNET) v6-Fähigkeit unklar**.
⚠️ **6to4 relay-abhängig/flatterhaft (empirisch: Google-ping scheitert) → KEINE Basis für Echtzeit-Medien.**
Saubere Alternative bei Bedarf: **6in4-Tunnelbroker** (Hurricane Electric, geroutetes /48). Details: Memory `project-ipv6-state`.
---
## Zwei natürliche Kontrollexperimente (das Rückgrat der Diagnose)
1. **Christophs nationale Videocalls = gut.** Damit sind bei *gleichem* Upload / WLAN / Kamera/Low-Light
ausgeschlossen: sein Upload, sein Roaming, seine Kamera-Bitrate **als Alleinursache**.
2. **Geli Cable/DSL → Fiber, Problem bleibt.** Damit ist Gelis **Last-Mile-Bandbreite** als Wurzel raus.
Was auf ihrer Seite konstant blieb: **derselbe Mini-ISP + CGNAT + die internationale Strecke** und die Cudy-WLAN.
→ Schnittmenge beider Experimente = die **Geli-seitige ISP-/Peering-/CGNAT-Strecke** als gemeinsamer Nenner.
---
## Was bereits AUSGESCHLOSSEN / herabgestuft ist
Messungen vom **Mac mini (Kabel, en0, VLAN20/INFRA, GW 10.40.20.1)**, 2026-06-16, **tagsüber im gesunden
Zustand** (deshalb sauber — der Mehrwert liegt im Mitschnitt **WÄHREND eines miesen Abend-Calls**).
| Hypothese | Befund | Urteil |
|---|---|---|
| Heim-Bufferbloat Christoph (Upload) | 3 Flows = 10.3 Mbit gesättigt → idle 12 ms, Vollast avg 17 / max 26 ms = A/A+ | ❌ kein Problem |
| Generischer AT→DE-Pfad | heise.de: 20.7 ms / Jitter 1.6 ms / 0 % Loss (40) | ❌ Pfad (tagsüber) top |
| Christoph → nächstes Telegram-DC | 149.154.167.50 (NL): 27 ms / Jitter 1.3 ms | ❌ Pfad (tagsüber) top |
| CAKE / QoS | kein Bufferbloat-Spielraum | ❌ **nicht deployt** (wäre marginal) |
| WARP / internat. Pfad | AT→DE tagsüber bereits 20 ms | ❌ **nicht deployt** |
| S2S-VPN-Tunnel (BF-FB ↔ Geli-FB WG) | Messenger = Cloud-Relay, nicht im Tunnel | ❌ **nicht im Call-Pfad** |
| Christophs lokale Seite (Upload/WLAN/Kamera) | **nationale Videocalls = gut** (Kontrollexp. 1) | ❌ keine Alleinursache |
| Gelis Last-Mile-**Bandbreite** | **Cable/DSL→Fiber, Problem bleibt** (Kontrollexp. 2) | ❌ nicht die Wurzel |
| **WLAN-Roaming/Handover** (ehem. Lead) | Cudy half *etwas*; still sitzen *etwas* besser, aber weiter mies; Hauptkorrelat ist **Licht**, nicht Bewegung | ⚠️ **Nebenfaktor**, nicht Wurzel |
| ~~Gelis CGNAT/Dorf-ISP durch Asymmetrie entlastet~~ | **VOID.** Gilt nur, wenn der Flaschenhals ihr *Access-Link* wäre. Sitzt er im **internat. Peering**, laufen Gelis *innerdeutsche* Calls nicht drüber → Asymmetrie bleibt erklärt | ⚠️ **wieder im Spiel** |
| Telegram-App-Bug/Codec | mehrere Messenger betroffen | ❌ entlastet |
| ~~Christoph WLAN -76 dBm auf `install-10`~~ | `install-10` = Testnetz, nicht produktiv | ⚠️ Fehlmessung, ignorieren |
---
## Leitende Hypothese: ratengebundenes Video über die Geli-Strecke
**Mechanik:** Echtzeit-Video-Congestion-Control (WebRTC/Telegram-artig) sucht die maximale Bitrate.
Schwer komprimierbares Bild (Gegenlicht/Dunkel → Sensorrauschen + Kontrast) treibt die **geforderte
Bitrate hoch**. Trifft das auf einen **engen/variablen Punkt der Geli-Strecke** (CGNAT-Session-Limit,
abends überlastetes Auslands-Peering eines Mini-AS), entstehen **Loss/Jitter**; der Bitraten-Schätzer
kollabiert und erholt sich nicht → genau das beobachtete „neuer Call kurz gut, dann Abbruch".
**Warum das alle Beobachtungen erklärt:**
| Beobachtung | Erklärung |
|---|---|
| Gegenlicht/Dunkel → Artefakte (auch tagsüber) | hohe Entropie → Bitraten-Spike → über den Engpass |
| „dunkel" gehäuft | Sensorrauschen **+** Abend-Peak-Last (dieselbe Richtung) |
| neuer Call kurz gut, dann Abbruch | Congestion-Control rampt in die Ratenwand, kollabiert, Reset hilft kurz |
| Kamera aus/ein hilft | senkt Bitrate → entlastet Engpass = bandbreitengebunden |
| nur mit Geli | nur dieser Pfad hat Mini-ISP + CGNAT + Auslands-Strecke; nationale Calls nicht |
| Roaming nur Nebenfaktor | „still = etwas besser, aber mies"; „Cudy half *etwas*" |
**Lokalisierung GEKLÄRT:** Christoph leidet stärker (hört/sieht Geli schlechter), Geli seltener →
Engpass sitzt dominant auf **Geli→Christoph = Gelis Senderichtung**. Innerhalb dieser Richtung ist die
Kette: **(1) Gelis WLAN-Uplink** (schwach an dicker Hausmauer/Distanz; Airtime nur fallweise, PS meist aus)
→ **(2) hohe Video-Bitrate** (Gegenlicht/Dunkel) → **(3) CGNAT/Auslands-Peering**
(abends). Die **Jitter-/Burst-Signatur** (verzögert-dann-stoßweise) zeigt: es ist primär **Queuing/Bufferbloat
auf dieser Senderichtung**, nicht reiner Random-Loss.
---
## Ausführungsplan (für die separate Session)
**Reihenfolge: erst beweisen, dann fixen.** Constraint: **passiv messen** während echter Calls
(„cave: verändert den Datenstrom"); **kein iperf/Sättigen** während eines laufenden Calls.
1. **Billige Sofort-Tests (heute Abend, ~0 €):**
- **Bitrate/Auflösung im Messenger deckeln** (z. B. Telegram-Datensparmodus) → wird's spürbar stabiler? = Mechanismus bestätigt.
- **Gelis Gegenlicht eliminieren** (Lampe von vorn, nicht Fenster im Rücken) → Artefakte weg/weniger?
- **Richtungstest:** beide notieren, wer wessen Aussetzer sieht (s. Lokalisierung oben).
2. **Messen — was lokalisiert wirklich? (wichtig: Sniffer-Grenze)**
- **Ein Call-Sniffer NUR auf Christophs Seite lokalisiert NICHT.** Was bei dir ankommt, hat Funk + ISP +
Transit bereits vermischt → zeigt nur das **Symptom** (eingehender Stream ruckelt/verliert, mit
Zeitstempel + Relay-IP), nicht **wo**. Verbleibende Unsicherheit = **Gelis Funk-Uplink vs. Gelis
ISP-Pfad** (≠ Fix!). Dafür braucht es einen Messpunkt **auf Gelis Seite**.
- **Remote machbar & aussagekräftig:** MTR/Ping-Log **Mac mini → Geli-FB `94.154.138.11`**, **abends
unter echter Call-Last vs. Tageswert** (22.2 ms / 0.88 ms / 0 % Loss). Degradiert der Pfad abends →
**ISP/Peering** schuld. Bleibt er sauber, Call trotzdem mies → Engpass liegt **in Gelis Funk/Relay**,
nicht im Transit. (Misst nur bis zur CGNAT-Grenze, nicht in ihr LAN.)
- **Auf Gelis Seite ohne Infra, nur per Handy:** **Bufferbloat-Test** (z. B. waveform.com/tools/bufferbloat)
auf **Gelis Handy abends** → zeigt direkt, ob **ihr Uplink unter Last aufbläht** (Latenz steigt) =
Anschluss/Funk. Einmalig, kein Setup.
- **A/B-Verhaltenstest (Handout) schlägt passives Sniffen:** ändert kontrolliert **eine** Variable
(nah am AP / gutes Licht / Audio-only / tags vs. abends) → lokalisiert besser, weil es Ursache *isoliert*.
- **Roaming nur sekundär:** Cudy-Stationen (RSSI/TX-RX/Retries/Assoc-Events) bei bewegtem Call —
Cudy ≠ MikroTik → kein MikroMCP; Cudy SSH+`iw station dump` rein lesend, falls möglich.
3. **Fix-Pfade (nach Lokalisierung) — Geli-Tal: nur dieser ISP oder schlechter Mobilfunk:**
- **(sofort, ISP-unabhängig)** Bitrate-Deckel (Telegram „weniger Daten") + **Ausleuchtung/kein Gegenlicht**
+ **Position nah am AP** + Calls eher **tagsüber** (Peak meiden) + **Audio-only** bei Bewegung.
- **(WLAN)** Zusätzlicher AP/nähere Funkstation an Gelis üblichem Call-Platz → stärkerer **Uplink** dort;
Band/Position so, dass das Handy nicht am fernen AP „klebt". TP3/CAPsMAN-802.11r adressiert den Roaming-Nebenfaktor.
- **(App/Codec)** **A/B mit anderem Dienst** (WhatsApp/Signal) abends — andere Congestion-Control kann auf
schlechtem Link robuster sein. Billiger Test, evtl. echter Gewinn. (FaceTime fällt aus: Geli = Android.)
- **(IPv6 — billigster Hebel, braucht NUR Gelis v6):** **Korrektur:** Telegram **unterstützt IPv6** (DCs dual-stack,
früher expliziter „Use IPv6"-Schalter); frühere Annahme „kann kein v6" war falsch. Die **schlechte Richtung
ist Geli→Christoph** (ihr Upload), erster Sprung = **Gelis Handy → Telegram-Reflector**. Geht *dieser* Leg über
v6, ist **Gelis CGNAT auf genau der kaputten Richtung umgangen** — das braucht **nur Gelis v6 (vorhanden),
NICHT Christophs**. Da ihre FB das LAN bereits mit v6 versorgt, **läuft das evtl. schon / ist 1 Schalter entfernt.**
**Verify (kein Ausbau):** auf Gelis Handy `test-ipv6.com` (Score) + Telegram-Daten-Einstellungen auf v6-Option prüfen.
**Offen/zu verifizieren:** ob aktuelle Clients den **VoIP-Reflector** über v6 ansprechen (Messaging-zu-DC = ja, Call-Reflector = wahrscheinlich).
**Caveat:** v6 umgeht nur die **CGNAT-Box**, NICHT das **Transit-Rohr** — bei Abend-Peering-Stau hilft v6 nicht.
- **(ISP-Intervention, falls Transit/Peering der Stau ist):** kleiner Lokal-ISP = eher erreichbar; Abend-Congestion
+ Peering nach AT schildern. CGNAT-Opt-out/öffentliche v4 nur nötig, falls v6-Weg nicht tragfähig.
- **(strukturell, TP10 — NUR Notnagel, kein Default):** eigener Medienpfad (WG-über-v6 FB↔ap1, dann self-hosted
Jitsi/SIP) **erst erwägen, wenn die Messung „Transit-Rohr" sagt** — also wenn auch v6 staut und der ISP nicht
hilft. Für den CGNAT-Fall **nicht nötig** (Gelis vorhandenes v6 reicht). ⚠️ **Christoph-seitig v6 blockiert**
(Liwest kein v6; 6to4 untauglich für RT-Medien) → bräuchte erst **6in4-Tunnelbroker (HE)** + DDNS für Gelis rotierendes /56.
---
## Benötigte Infos / Zugänge (von Christoph)
- **Richtung der Artefakte** (wer sieht wessen Aussetzer) — der wichtigste offene Fakt.
- **Cudy-Modell** + Zugangsweg (SSH/Web-UI/App, Creds) — für den sekundären Roaming-Check, beide Seiten.
- **Anruf-Gerät** (Handy/Modell) — Client-seitige Korrelation, Kamera/Codec-Verhalten bei Low-Light.
- Gelis **Fiber-Tarif** (Up/Down) + Bestätigung **weiterhin CGNAT** (`on-isp.net`).
## Constraints / Caveats
- **Passiv only** während echter Calls.
- **MikroMCP** verwaltet die **Cudys nicht**.
- **ap1 ist unverändert** — keine QoS-/Firewall-/Queue-Änderung appliziert (Details unten).
- Tagesmessungen waren sauber, **weil im gesunden Zustand** — nicht als Entlastung des Abend-Pfads werten.
## Zustand ap1 (zur Sicherheit dokumentiert — NICHTS wurde geändert)
- Keine Queues, kein CAKE. **Fasttrack `*8` weiter aktiv.** Keine neuen Mangle-Regeln.
- WAN-Egress aktuell = `bridge` → FB (10.40.41.254); masquerade `out-interface=bridge` (TP4).
- ether1-Direkt-WAN bleibt vorkonfiguriert/down (gated auf TP10).
## Querverweise
- **TP10** (VPN/CGNAT) — jetzt **aufgewertet**: Gelis FB `94.154.138.11:52727` (Fiber, CGNAT), AS202245
Geroldsgrün; Hub-Spoke auf ap1 (Geli wählt ausgehend ein, PersistentKeepalive ~25 s). Memory:
`project_ap_vpn_bridge_blocker.md`.
- **TP3** (WLAN/CAPsMAN, 802.11r/k/v) — Fix für den **Roaming-Nebenfaktor**, nicht die Wurzel.
- `docs/research/routeros-capabilities.md` — Fast-Roaming-Konzept.
## Messdaten-Anhang (Rohwerte 2026-06-16, Tageslicht/gesund)
- Upload-Sättigung Christoph: 3 Flows × ~430 KB/s = 1.28 MB/s = **10.3 Mbit** (sustained).
- Bufferbloat Christoph: idle 12 ms; Vollast avg 17.5 / max 26 ms (24 Pings).
- AT→heise.de: min 19.3 / avg 20.7 / max 27.6 / stddev 1.6 ms, 0 % Loss (40).
- AT→Telegram 149.154.167.50: avg 26.9 ms / stddev 1.3 ms (29/30); 91.108.56.130 = 173 ms (fernes DC, irrelevant).
- BF→Geli-FB 94.154.138.11: avg 22.2 / stddev 0.88 ms, 0 % Loss (30); rDNS `nat-3.aigbng02.bng.on-isp.net` = CGNAT.
⚠️ **Tageswert** — Referenz für den Abend-Vergleich, kein Freispruch.
- Testnetz-Client (VOID): `install-10`, 5 GHz, WPA3-PSK, -76 dBm — nicht das produktive Netz.