QoS & Traffic Shaping

1. Einführung – Warum QoS?

Wer zuhause ein Heimnetz betreibt, das mehr als nur gelegentliches Surfen leistet, kennt das Problem: Während jemand eine große Datei herunterlädt, beginnt das VoIP-Gespräch zu ruckeln, die Gaming-Latenz schießt in die Höhe, oder das Video-Meeting friert ein. Ursache ist in den meisten Fällen kein zu langsamer Anschluss, sondern fehlende Priorisierung des Netzwerkverkehrs – also fehlende Quality of Service (QoS).

QoS ist der Oberbegriff für Mechanismen, die sicherstellen, dass bestimmte Datenströme bevorzugt behandelt werden. Dabei geht es nicht primär darum, mehr Bandbreite bereitzustellen, sondern darum, die vorhandene Bandbreite intelligent zu verteilen und Verzögerungen gezielt zu minimieren.

Ein besonders häufig unterschätztes Problem ist Bufferbloat. Moderne Router und Modems verwenden oft sehr große Puffer, um Paketverluste zu vermeiden. Das klingt zunächst sinnvoll, führt aber dazu, dass Pakete lange in diesen Puffern warten, bevor sie gesendet werden. Die Folge ist eine stark erhöhte und schwankende Latenz, selbst wenn die Verbindung nicht vollständig ausgelastet ist. Ein einfacher Test mit ping während eines aktiven Downloads zeigt dieses Verhalten deutlich: Die Antwortzeiten steigen von wenigen Millisekunden auf mehrere hundert Millisekunden.

Für latenzempfindliche Anwendungen wie VoIP (Voice over IP), Online-Gaming oder Videokonferenzen ist Bufferbloat fatal. QoS-Mechanismen lösen dieses Problem, indem sie Puffer kontrolliert leeren, Pakete priorisieren und den Durchfluss so formen, dass kein einzelner Datenstrom die gesamte verfügbare Kapazität monopolisiert.

2. Grundbegriffe

Um QoS zu verstehen, müssen einige grundlegende Begriffe klar sein, die oft verwechselt oder unscharf verwendet werden.

Bandbreite bezeichnet die maximale Datenmenge, die pro Zeiteinheit über eine Verbindung übertragen werden kann – üblicherweise in Mbit/s oder Gbit/s gemessen. Bandbreite ist eine Kapazitätsangabe, keine Qualitätsaussage.

Latenz (auch Round-Trip Time, RTT) ist die Zeit, die ein Paket benötigt, um von der Quelle zum Ziel und zurück zu gelangen. Für interaktive Anwendungen wie Gaming oder VoIP ist niedrige Latenz entscheidend. Typische Werte in Heimnetzwerken: unter 10 ms im LAN, 10–40 ms bei einer guten DSL-/Kabelverbindung ins Internet.

Jitter bezeichnet die Schwankung der Latenz über die Zeit. Konstante Latenz ist besser als niedrige, aber stark schwankende Latenz. VoIP-Codecs können moderate Latenz kompensieren, aber hoher Jitter führt zu Sprachaussetzern, da Pakete in unregelmäßigen Abständen eintreffen.

Queuing Delay ist die Verzögerung, die entsteht, weil ein Paket in einer Warteschlange wartet, bevor es gesendet werden kann. Dieser Wert ist direkt durch QoS-Mechanismen beeinflussbar.

Policing und Shaping sind zwei unterschiedliche Ansätze zur Ratenbegrenzung. Beim Policing werden Pakete, die eine definierte Rate überschreiten, sofort verworfen (Drop) oder markiert. Das ist schnell, kann aber zu Paketverlusten führen. Beim Shaping werden Pakete hingegen in einem Puffer zwischengespeichert und zeitverzögert gesendet, sodass die Rate geglättet wird. Shaping ist schonender, erhöht aber die Latenz leicht. Für ausgehenden Verkehr ist Shaping meist die bessere Wahl.

3. DSCP und IP-Precedence

Um Pakete priorisieren zu können, müssen sie zunächst klassifiziert und markiert werden. Historisch wurde dafür das IP-Precedence-Feld im IPv4-Header genutzt – drei Bits im Type-of-Service-Byte (ToS), die acht Prioritätsstufen (0–7) ermöglichten. Dieses Verfahren war einfach, aber zu grob für moderne Anforderungen.

Mit RFC 2474 wurde das ToS-Byte zu einem Differentiated Services (DiffServ)-Feld umdefiniert. Die oberen sechs Bits bilden den DSCP (Differentiated Services Code Point), was 64 mögliche Werte ergibt. Damit lassen sich Verkehrsklassen wesentlich feiner unterscheiden.

Die wichtigsten standardisierten DSCP-Klassen sind:

  • EF (Expedited Forwarding, DSCP 46 / 0x2E): Höchste Priorität, gedacht für latenzempfindlichen Echtzeit-Verkehr wie VoIP-Audio. Pakete mit EF-Markierung sollen mit minimaler Verzögerung und ohne Jitter weitergeleitet werden.
  • AF (Assured Forwarding, AFxy): Vier Klassen (AF1x–AF4x) mit je drei Drop-Precedence- Stufen (1, 2, 3). AF41 wird typischerweise für Videokonferenzen verwendet, AF31 für Signaling, AF11 für Hintergrundverkehr mit garantierter Mindestbandbreite.
  • BE (Best Effort, DSCP 0): Standard ohne Priorisierung. Der Großteil des Internetverkehrs fällt in diese Kategorie.
  • CS (Class Selector): Abwärtskompatibel mit IP-Precedence; CS6 und CS7 sind für Netzwerk-Control-Traffic reserviert (z. B. OSPF, BGP).

Pakete können an verschiedenen Stellen markiert werden: auf dem Endgerät selbst (Windows und Linux können DSCP-Bits in ausgehenden Paketen setzen), auf dem Router (anhand von Port-Nummern, Protokollen oder IP-Adressen) oder an Layer-2-Switches über 802.1p CoS-Bits. Wichtig: DSCP-Markierungen werden von Internetprovidern häufig ignoriert oder überschrieben, weshalb QoS im Heimnetz meist nur auf dem eigenen Router sinnvoll zu erzwingen ist.

Unter Linux lässt sich eine DSCP-Markierung mit iptables oder nftables setzen. Beispiel mit iptables, um ausgehenden SIP/RTP-Verkehr mit EF zu markieren:

iptables -t mangle -A OUTPUT -p udp --dport 5060 -j DSCP --set-dscp-class EF
iptables -t mangle -A OUTPUT -p udp --dport 10000:20000 -j DSCP --set-dscp-class EF

4. Queuing-Disziplinen unter Linux

Linux verfügt über ein mächtiges, aber komplexes Framework zur Verkehrssteuerung: den Traffic Control-Subsystem (tc). Kern des Systems sind sogenannte Queuing Disciplines (qdiscs) – Warteschlangen-Algorithmen, die bestimmen, in welcher Reihenfolge und mit welcher Rate Pakete gesendet werden.

pfifo (Packet FIFO) ist die einfachste Disziplin: Pakete werden in der Reihenfolge ihres Eintreffens gesendet, First In, First Out. Kein Shaping, keine Priorisierung. Bei voller Auslastung entstehen lange Warteschlangen und damit Bufferbloat.

fq_codel (Fair Queue Controlled Delay) ist ein moderner Algorithmus, der gezielt Bufferbloat bekämpft. Er kombiniert zwei Konzepte: Fair Queueing teilt die Bandbreite fair auf alle aktiven Flows auf, sodass ein einzelner TCP-Download nicht alle anderen Verbindungen verdrängen kann. CoDel (Controlled Delay) misst die tatsächliche Wartezeit von Paketen in der Queue und verwirft Pakete aktiv (AQM – Active Queue Management), sobald die Verzögerung einen definierten Schwellwert (typisch 5 ms) überschreitet. TCP reagiert darauf mit einer Reduktion seiner Senderate, was den Puffer entleert und die Latenz niedrig hält. fq_codel ist seit Linux 3.5 verfügbar und ist unter vielen Distributionen die Standarddisziplin.

HTB (Hierarchical Token Bucket) ist das Mittel der Wahl, wenn Bandbreite garantiert oder begrenzt werden soll. HTB organisiert Verkehr in einer Baumstruktur aus Klassen. Jede Klasse hat eine garantierte Rate (rate) und eine maximale Rate (ceil). Überschüssige Bandbreite wird an untergeordnete Klassen weitergegeben, die ihre garantierte Rate bereits erreicht haben, sofern die Parent-Klasse noch Kapazität hat.

Ein praktisches Beispiel: Ein Heimnetz mit einem Upstream von 50 Mbit/s soll VoIP priorisieren und den restlichen Verkehr fair aufteilen. Dabei wird absichtlich etwas weniger als der volle Upstream konfiguriert (hier 48 Mbit/s), um dem Router-internen Puffer keine Chance zu geben, Bufferbloat zu verursachen.

# Bestehende qdiscs entfernen
tc qdisc del dev eth0 root 2>/dev/null

# HTB als Root-Qdisc, default-Klasse 30 (Best Effort)
tc qdisc add dev eth0 root handle 1: htb default 30

# Root-Klasse: Gesamtbandbreite 48 Mbit/s
tc class add dev eth0 parent 1: classid 1:1 htb rate 48mbit ceil 48mbit

# VoIP-Klasse: 4 Mbit/s garantiert, bis zu 48 Mbit/s wenn frei
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 4mbit ceil 48mbit prio 1

# Interaktiv (Gaming, SSH): 10 Mbit/s garantiert
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 10mbit ceil 48mbit prio 2

# Best Effort (HTTP, Downloads): 34 Mbit/s
tc class add dev eth0 parent 1:1 classid 1:30 htb rate 34mbit ceil 48mbit prio 3

# fq_codel als Leaf-Qdisc für jede Klasse (Bufferbloat-Schutz)
tc qdisc add dev eth0 parent 1:10 handle 10: fq_codel
tc qdisc add dev eth0 parent 1:20 handle 20: fq_codel
tc qdisc add dev eth0 parent 1:30 handle 30: fq_codel

# Filter: VoIP-Verkehr anhand DSCP EF (46) in Klasse 1:10
tc filter add dev eth0 parent 1: protocol ip u32 \
  match ip dsfield 0xb8 0xfc flowid 1:10

# Filter: Interaktiver Verkehr anhand DSCP AF41 (34) in Klasse 1:20
tc filter add dev eth0 parent 1: protocol ip u32 \
  match ip dsfield 0x88 0xfc flowid 1:20

Dieses Setup stellt sicher, dass VoIP-Pakete stets bevorzugt behandelt werden, während Downloads die verbleibende Kapazität nutzen können. Der Einsatz von fq_codel als Leaf-Qdisc verhindert innerhalb jeder Klasse erneut Bufferbloat.

5. QoS auf OPNsense/pfSense

OPNsense und pfSense sind auf FreeBSD basierende Firewall-Distributionen, die in vielen Homelabs und kleinen Unternehmen als Router eingesetzt werden. Beide unterstützen QoS über den HFSC (Hierarchical Fair Service Curve)-Shaper, der leistungsfähiger als HTB ist, aber auch eine steilere Lernkurve hat.

HFSC erlaubt es, neben der Bandbreite auch die Latenz pro Klasse zu garantieren. Über sogenannte Service Curves lässt sich exakt definieren, wie viel Bandbreite eine Klasse über welchen Zeitraum erhält. Das ist besonders nützlich für VoIP, wo nicht nur die Bitrate, sondern auch die maximale Verzögerung begrenzt werden muss.

Konfigurationsbeispiel in OPNsense für VoIP-Priorisierung:

Unter Firewall > Shaper > Pipes werden zunächst Pipes erstellt, die die physische Bandbreite repräsentieren. Anschließend werden unter Queues die Warteschlangen mit Prioritäten und Gewichtungen definiert, und unter Rules wird der Verkehr den Queues zugeordnet.

  • Pipe WAN-Upload: Bandbreite 48 Mbit/s (leicht unter dem tatsächlichen Upstream, um Bufferbloat am Modem zu verhindern).
  • Queue VoIP: Priorität 7 (höchste), Gewicht 100, Zuordnung zur Upload-Pipe. Hier wird RTP-Verkehr (UDP 10000–20000) und SIP (UDP/TCP 5060) eingeordnet.
  • Queue Interactive: Priorität 5, Gewicht 30. SSH (TCP 22), DNS (UDP 53), HTTPS für interaktive Webseiten.
  • Queue BulkData: Priorität 2, Gewicht 10. HTTP-Downloads, Cloud-Backups, Torrent-Verkehr.

Die Regeln unter Rules werden nach Protokoll, Quell- und Zielport sowie Quell-IP definiert. Eine Regel könnte lauten: Alle UDP-Pakete von der lokalen VoIP-Telefonanlage (z. B. 192.168.1.50) mit Zielport 10000–20000 werden der Queue VoIP zugewiesen.

Ein häufiger Fehler bei der OPNsense/pfSense-Konfiguration ist, den Shaper nur für ausgehenden Verkehr (WAN-Upload) zu konfigurieren und eingehenden Traffic zu vergessen. Da eingehende Pakete am WAN-Interface bereits ankommen, bevor sie beeinflusst werden können, muss der Downstream indirekt geformt werden: indem der Upload auf dem WAN-Interface gedrosselt wird, signalisiert TCP der Gegenstelle, langsamer zu senden, was den Download-Puffer am Modem entleert.

6. CAKE – Common Applications Kept Enhanced

CAKE (Common Applications Kept Enhanced) ist eine modernere Queuing-Disziplin, die als konzeptioneller Nachfolger von fq_codel entwickelt wurde. CAKE integriert mehrere Techniken in einem einzigen, einfach zu konfigurierenden Algorithmus: Fair Queueing, AQM und optionales Traffic Shaping. Es wurde im Rahmen des Bufferbloat-Projekts entwickelt und ist seit Linux 4.19 im Mainline-Kernel enthalten.

Der entscheidende Vorteil von CAKE gegenüber fq_codel liegt in seiner dreifachen Isolierung: CAKE unterscheidet Flows nach Hosts (src/dst IP) und Verbindungen. Damit verhindert es, dass ein einzelner Host oder eine einzelne Verbindung die Bandbreite dominiert – selbst wenn dieser Host viele parallele TCP-Verbindungen aufbaut (was beim klassischen Fair Queueing zu einer Bevorzugung führen würde).

CAKE unterstützt außerdem Overhead-Kompensation. DSL-Verbindungen haben durch ATM-Framing oder PPPoE einen Overhead pro Paket, der die effektiv nutzbare Bandbreite leicht reduziert. CAKE kann diesen Overhead exakt modellieren, sodass die konfigurierten Raten wirklich der nutzbaren Bandbreite entsprechen.

Auf einem Linux-Router oder unter OpenWrt lässt sich CAKE mit einem einzigen Befehl aktivieren. Das folgende Beispiel konfiguriert CAKE auf dem WAN-Interface für ausgehenden Verkehr mit 50 Mbit/s, aktiviert Dual-Stack-Fairness (separate Queues für IPv4 und IPv6) und gibt an, dass die Verbindung einen PPPoE-Overhead hat:

tc qdisc add dev eth0 root cake bandwidth 50mbit \
  dual-srchost \
  nat \
  overhead 18 \
  atm

Unter OpenWrt ist CAKE über das Paket kmod-sched-cake und das SQM (Smart Queue Management)-Framework verfügbar. Die Konfiguration erfolgt über die grafische Oberfläche unter Network > SQM QoS. Dort kann das Script cake.qos ausgewählt und die Bandbreite für Up- und Downstream eingetragen werden. OpenWrt ermittelt auf Wunsch auch automatisch die korrekte Overhead-Einstellung anhand des gewählten Verbindungstyps (VDSL, ADSL, PPPoE, Ethernet).

CAKE mit SQM ist für die meisten Heimnetz-Szenarien die empfohlene Lösung, da es ohne tiefes Verständnis von Queuing-Hierarchien sofort wirksam ist und Bufferbloat zuverlässig beseitigt.

7. Troubleshooting

Wenn QoS konfiguriert ist, aber nicht wie erwartet funktioniert, oder wenn man die aktuelle Konfiguration verstehen möchte, stehen unter Linux und im Netzwerk einige hilfreiche Werkzeuge zur Verfügung.

tc qdisc show zeigt alle aktiven Queuing-Disziplinen auf allen Interfaces:

tc qdisc show dev eth0

Die Ausgabe zeigt Root-Qdisc, Handle und Parameter. Wenn nur pfifo_fast angezeigt wird, ist noch kein QoS aktiv konfiguriert.

tc -s qdisc show liefert zusätzlich Statistiken: gesendete Pakete, Bytes, verworfene Pakete (dropped) und Überschreitungen (overlimits). Hohe dropped-Werte bei einer Klasse deuten darauf hin, dass die konfigurierte Rate zu niedrig ist oder der Verkehr falsch klassifiziert wurde.

tc -s qdisc show dev eth0
tc -s class show dev eth0

tc -s class show zeigt für HTB-Hierarchien die einzelnen Klassen mit ihren Statistiken. Wichtig sind hier die Felder rate (aktuelle Senderate), ceil (erlaubtes Maximum) und lended/borrowed (ob eine Klasse Bandbreite an untergeordnete Klassen verliehen oder von übergeordneten geliehen hat).

iperf3 ist das Standard-Tool zum Messen der tatsächlich erzielbaren Bandbreite und zur Überprüfung von QoS-Konfigurationen. Ein iperf3-Server wird mit iperf3 -s gestartet, der Client verbindet sich mit iperf3 -c <server-ip>. Mit dem Flag -S lässt sich der DSCP-Wert im ausgehenden Verkehr setzen:

# Messung mit EF-Markierung (DSCP 46)
iperf3 -c 192.168.1.1 -S 0xb8 -t 10

# Parallele Streams, um mehrere Flows zu simulieren
iperf3 -c 192.168.1.1 -P 4 -t 30

Zum Messen von Bufferbloat empfiehlt sich das Tool Waveform Bufferbloat Test (online unter waveform.com/tools/bufferbloat) oder das Kommandozeilen-Tool flent (Flexible Network Tester), das gleichzeitig Bandbreite und Latenz misst und grafisch darstellt:

# RRUL-Test (Realtime Response Under Load) gegen einen netperf-Server
flent rrul -p all_scaled -H 192.168.1.1 -t "Vor QoS" -o vor-qos.png

Ein sauber konfiguriertes QoS-System sollte auch unter Volllast einen Ping von unter 20 ms zum nächsten Router halten. Wenn das gelingt, ist Bufferbloat erfolgreich eliminiert und latenzempfindliche Anwendungen profitieren spürbar. Wer seine Konfiguration schrittweise aufbaut, sollte vor und nach jeder Änderung messen – nur so lässt sich nachweisen, ob ein Eingriff tatsächlich eine Verbesserung gebracht hat.