Ich zeige, wie Bandwidth Shaping auf Servern und Traffic Control in Linux die Paketflüsse so steuert, dass Latenz, Jitter und Ausfälle spürbar sinken. Dabei setze ich priorisierte Queues, Limits und QoS-Regeln gezielt ein, um geschäftskritische Ströme wie VoIP, APIs oder Shop-Requests vor Hintergrundlasten und Backups zu schützen.
Zentrale Punkte
Die folgenden Kernaussagen helfen mir, Bandbreiten und Verkehr auf Linux-Servern zielgerichtet zu kontrollieren und dauerhaft planbar zu machen.
- Priorisierung zeitkritischer Flows senkt Latenz und Jitter.
- Rate-Limits und Throttling vermeiden Bursts und Pufferstaus.
- HTB/SFQ verteilen Bandbreite fair und halten Klassen konstant.
- QoS-Filter steuern nach IP, Port, Protokoll oder Markierungen.
- Monitoring via P95 und Alerts deckt Engpässe früh auf.
Diese Punkte baue ich schrittweise auf, messe Effekte kontinuierlich und passe Klassen sowie Raten an reale Nutzung an.
Was Bandwidth Shaping konkret bedeutet
Beim Shaping reguliere ich den Paketfluss aktiv, statt nur reaktiv zu drosseln. Ich halte Raten konstant, priorisiere Echtzeit- und Interaktiv-Verkehr und glätte unregelmäßige Datenbursts. Dazu setze ich auf Rate Limiting für ausgehenden Traffic und Throttling für eingehenden Datenstrom. Diese Trennung schafft klare Zuständigkeiten pro Richtung und verhindert vollgelaufene Puffer. Für Hosting-Umgebungen stelle ich pro Kunde oder Anwendung definierte Obergrenzen ein, damit eine Lastspitze nicht das gesamte System ausbremst.
Traffic Control in Linux: Werkzeuge und Konzepte
Unter Linux steuere ich Verkehr mit dem Tool tc und den Kernel-Queuing-Disziplinen (qdisc). Typische Bausteine sind Wurzel-qdisc, Klassen und Filter, die die Zuordnung von Paketen zu Prioritäten und Limits festlegen. Ich starte oft mit HTB als hierarchischem Regler für garantierte und maximale Raten. Ergänzend setze ich SFQ für gerechte Verteilung innerhalb einer Klasse ein. So beschränke ich Bandbreite auf 90–95 Prozent der physisch möglichen Rate, um Burst-Headroom zu behalten und Latenzspitzen zu vermeiden.
Eingangs‑Shaping (Ingress): IFB statt Policer
Für eingehenden Verkehr forme ich nicht direkt auf dem physikalischen Interface, sondern nutze ein IFB-Device (Intermediate Functional Block). Ich spiegele Ingress-Pakete auf das IFB und behandle sie dort wie ausgehenden Traffic – inklusive HTB-Hierarchie, Fairness und Limits. Das ist feiner als ein reiner Policer, der nur hart verwirft und oft Jitter erhöht.
modprobe ifb numifbs=1
ip link add ifb0 type ifb
ip link set dev ifb0 up
# Ingress am PHY aktivieren und auf IFB umlenken
tc qdisc add dev eth0 handle ffff: ingress
tc filter add dev eth0 parent ffff: protocol ip u32 match u32 0 0 \
action mirred egress redirect dev ifb0
# Shaping auf dem IFB wie bei Egress
tc qdisc add dev ifb0 root handle 2: htb default 20
tc class add dev ifb0 parent 2: classid 2:10 htb rate 40mbit ceil 60mbit
tc class add dev ifb0 parent 2: classid 2:20 htb rate 20mbit ceil 40mbit
tc qdisc add dev ifb0 parent 2:10 handle 210: fq_codel
tc qdisc add dev ifb0 parent 2:20 handle 220: sfq
Mit IFB gewinne ich Kontrolle über Download-Peaks, etwa wenn Backup- oder Mirror-Jobs eingehend Bandbreite binden. In der Praxis richte ich IFB auf Schnittstellen mit stark asymmetrischen Raten (z. B. 1G/200M) oder wo eingehende Bursts Interaktivität gefährden.
HTB, TBF und SFQ im Vergleich
Für die richtige Wahl der qdisc schaue ich auf Anwendungsziele: Garantien, Burst-Verhalten und Fairness. HTB bietet hierarchische Klassen mit festen und maximalen Raten, TBF begrenzt streng per Token-Bucket, SFQ verteilt Chancen über Flows. In Kombination bilden sie in der Praxis ein belastbares Gerüst: HTB deckelt und garantiert, SFQ verhindert Dominanz einzelner Verbindungen, TBF bändigt hartnäckige Bursts. Die folgende Tabelle fasst Kernmerkmale für typische Server-Szenarien zusammen. So entscheide ich schneller, welche Disziplin an welcher Stelle Sinn ergibt.
| qdisc/Feature | Zweck | Stärken | Typischer Einsatz |
|---|---|---|---|
| HTB | Hierarchie und Rate-Kontrolle | Garantierte Rate, Obergrenze, Vererbung | Mandanten, Service-Klassen, QoS-Profile |
| TBF | Striktes Deckeln | Einfach, sehr deterministisch | Uplink-Cap, harte App-Limits |
| SFQ | Fairness je Flow | Geringe Overhead, gute Verteilung | Downloads, P2P, viele Sessions |
| FQ_CoDel | AQM gegen Bufferbloat | Niedrige Latenz, Queue-Entschärfung | Edge-Router, Latenz-kritische Links |
Für Zugänge mit deutlich schwankenden RTTs nutze ich FQ_CoDel oder – je nach Kernel – auch CAKE als Allrounder. In der Serverpraxis bleibe ich jedoch bei HTB+SFQ/FQ_CoDel, weil ich damit Garantien, Borrowing und faire Verteilung sauber in einer Hierarchie kombiniere.
Praxis: tc-Regeln für typische Server
Ich beginne mit einer einfachen HTB-Struktur und ordne danach per Filter zu. Eine Wurzel-qdisc mit Default-Klasse fängt unklassifizierte Pakete, priorisierte Klassen erhalten garantierte Raten. Danach verfeinere ich die Filter: HTTP/S auf Klasse A, Datenbank-Replikation auf Klasse B, Backups auf Klasse C. So bleiben Shop-Requests schnell, während Backups die Reste nutzen. Für Grundlagen und Wortschatz verweise ich auf diesen Einstieg zu Bandbreiten-Management, der das Vorgehen greifbar macht.
tc qdisc add dev eth0 root handle 1: htb default 20
tc class add dev eth0 parent 1: classid 1:10 htb rate 50mbit ceil 70mbit
tc class add dev eth0 parent 1: classid 1:20 htb rate 20mbit ceil 50mbit
tc class add dev eth0 parent 1: classid 1:30 htb rate 10mbit ceil 30mbit
tc qdisc add dev eth0 parent 1:10 handle 110: sfq
tc qdisc add dev eth0 parent 1:20 handle 120: sfq
tc qdisc add dev eth0 parent 1:30 handle 130: sfq
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dport 443 0xffff flowid 1:10
tc filter add dev eth0 protocol ip parent 1:0 prio 2 u32 match ip dport 3306 0xffff flowid 1:20
tc filter add dev eth0 protocol ip parent 1:0 prio 3 u32 match ip sport 22 0xffff flowid 1:30
Klassifizierung mit DSCP und Marks (IPv4/IPv6‑tauglich)
Damit Filter unabhängig von IP-Version und NAT greifen, markiere ich Pakete früh und mappe dann per fwmark in Klassen. So spare ich komplexe u32-Matches und halte Regeln schlank. DSCP nutze ich zusätzlich für End-to-End-Semantik, z. B. für VoIP oder Interaktivität.
# Beispiel mit nftables: TLS priorisieren, Backups drosseln
nft add table inet mangle
nft add chain inet mangle prerouting { type filter hook prerouting priority -150; }
nft add rule inet mangle prerouting tcp dport 443 meta mark set 10
nft add rule inet mangle prerouting tcp dport 22 meta mark set 30
nft add rule inet mangle prerouting tcp dport 873 meta mark set 40 # rsync/Backups
# Mapping in HTB-Klassen (wirken für IPv4/IPv6 gleichermaßen)
tc filter add dev eth0 parent 1:0 prio 1 handle 10 fw flowid 1:10
tc filter add dev eth0 parent 1:0 prio 2 handle 30 fw flowid 1:30
tc filter add dev eth0 parent 1:0 prio 3 handle 40 fw flowid 1:20
Wichtig: DSCP/Markierungen setze ich möglichst am Rand (Eingang der Maschine oder davor), damit spätere Entscheidungen schnell fallen und tc unter Last weniger Arbeit hat.
QoS-Strategien für Hosting: Fairness und Limits
In Multi-Tenant-Setups sichere ich Fairness über feste Garantien pro Kunde und Caps pro Anwendung. Ich markiere Pakete per DSCP oder nach Ports und weise sie passenden Klassen zu. Downloads und Backups dürfen Kapazität füllen, während interaktive Sessions bevorzugt laufen. Auf diese Weise bleiben SLA-relevante Dienste priorisiert, ohne andere Mieter auszuschließen. Praktische Szenarien und Priorisierungslogik fasse ich in diesem Überblick zu Traffic-Priorisierung zusammen, der gut zu tc-Regeln passt.
Persistenz und Automatisierung
Meine QoS-Policies überleben Reboots und Interface-Neustarts. Ich hinterlege tc-Befehle als idempotentes Skript und binde es in systemd oder netplan/networkd ein. Für Geräte mit dynamischen Namen (z. B. veth/tap) nutze ich udev-Regeln oder systemd-Templates.
# /usr/local/sbin/tc-setup.sh (idempotent bauen)
#!/bin/sh
tc qdisc replace dev eth0 root handle 1: htb default 20
# ... weitere Klassen/Filter hier
# systemd unit: /etc/systemd/system/tc-setup.service
[Unit]
Description=Traffic Control Setup
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/tc-setup.sh
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Änderungen rolle ich kontrolliert aus: erst auf Staging, dann zeitlich begrenzt im Produktivsystem (tc replace statt add), begleitet von Metriken und einem Rollback-Knopf.
Monitoring, P95 und Fehlersuche ohne Frust
Ich messe Effekte fortlaufend, statt mich auf Bauchgefühl zu verlassen. P95-Latenzen, Queue-Längen und Paketverluste zeigen, ob Regeln greifen oder zu streng wirken. Tools wie iftop, vnStat und Netdata machen Lastspitzen sichtbar, Logs von tc und iptables zeigen die Zuordnung. Tritt Jitter auf, reduziere ich Ceil-Werte leicht und prüfe CoDel/FQ_CoDel als AQM-Maßnahme. Bei Engpässen passe ich Klassengewichte schrittweise an und halte nach jeder Änderung Messfenster ein.
Testmethodik: Lastsimulation und Verifikation
Ich simuliere realistische Szenarien: ein Dauerstrom (iperf3), parallel dazu kurze Interaktionen (kleine HTTP-Requests) und periodische Bursts (Backup/rsync). Danach prüfe ich, ob interaktive Flows konstant niedrige Latenz halten und Bursts sauber geglättet werden.
# Gegenrichtung testen (Download/Ingress)
iperf3 -c <server> -R -t 60
# Shaping-Statistiken lesen
tc -s qdisc show dev eth0
tc -s class show dev eth0
# Jitter/RTT-Verteilung prüfen
ping -i 0.2 -c 100 <ziel> | awk '/time=/{print $7}' Wenn Klassen dauerhaft Borrows benötigen, erhöhe ich garantierte Raten leicht. Häufen sich Drops in AQM-Queues, prüfe ich Puffergrößen und ob Limits zu aggressiv gesetzt sind.
Performance-Tuning: 90–95 % Deckel, Burst-Glättung, MTU
Ich limitiere die Ausgaberate auf 90–95% des Link-Speeds, um Pufferbloat zu vermeiden und AQM wirken zu lassen. Bursts glätte ich mit Token-Bucket-Parametern (rate, burst/latency), damit kurzzeitige Spitzen nicht ganze Queues füllen. Die MTU überprüfe ich, um Fragmentierung zu reduzieren und Path-MTU-Probleme zu vermeiden. Bei stark schwankenden Workloads lege ich großzügige Ceil-Werte fest, aber konservative garantierte Raten. Dieses Setup hält Prior-Verkehr schnell, während Hintergrundprozesse neutral weiterlaufen.
Hardware‑Offloads, Multiqueue und IRQ‑Tuning
Für präzises Shaping auf schnellen Links kenne ich das Zusammenspiel mit NIC‑Offloads. TSO/GSO/GRO beschleunigen zwar, können aber bei sehr niedrigen Zielraten die Feinkörnigkeit verschlechtern. Für sensible Links schalte ich testweise TSO/GSO ab und messe Latenz/CPU-Gewinn gegen. Auf Multiqueue‑NICs setze ich eine mq-Wurzel-qdisc und konfiguriere darunter pro Queue HTB oder FQ_CoDel. CPU‑Last verteile ich mit RPS/XPS und IRQ‑Pinning, damit QoS-Arbeit nicht auf einer CPU verhungert.
# Offloads selektiv testen (vorsichtig in Produktion)
ethtool -K eth0 tso off gso off gro off
# Multiqueue-Layout
tc qdisc add dev eth0 root handle 1: mq
tc qdisc add dev eth0 parent 1:1 handle 10: htb default 20
tc qdisc add dev eth0 parent 1:2 handle 20: htb default 20
# ... pro Queue weiterführen und Klassen/Filter wie gewohnt setzen
Mit txqueuelen, Ringpuffergrößen und IRQ‑Affinity trimme ich die Latenz weiter. Ziel ist ein stabiler, kurzer Queue‑Pfad, der unter Last nicht kippt.
Sicherheit und Segmentierung: Shaping mit Firewall und VLAN
Ich kombiniere QoS mit Segmentierung, damit kritische Netze eigene Kapazitäten behalten. Pro VLAN oder Interface setze ich eigene Queues, Firewalls markieren bereits beim Eintritt in den Server. So muss tc weniger Entscheidungen unter Last treffen, weil Pakete früh klassifiziert sind. Backups aus dem Storage-VLAN bleiben auf ihrer Bahn, während Frontend-HTTP nicht verhungert. Die Trennung verkürzt zudem Fehleranalysen, weil Flows eindeutiger zuordenbar sind.
Virtualisierung und Container: Wo ich forme
In KVM/virtio‑Setups forme ich am bevorzugten Edge: am Bridge‑Interface (br0), am physischen Uplink (eth0) oder gezielt pro Gast auf dessen vnet‑Interface. Pro‑Tenant‑Garantien setze ich gern auf vnetX um, globale Caps auf dem Uplink. In Kubernetes ist tc an veth‑Peers oder Node‑Uplinks praktikabel; Markierungen vergebe ich früh per CNI/iptables/nftables, damit die Zuteilung deterministic bleibt. Für SR‑IOV oder DPDK achte ich darauf, dass die Datenpfade tc überhaupt noch durchlaufen – sonst forme ich davor oder nutze NIC‑eigene Rate‑Limiter.
Kosten und Nutzen: Effizienz statt Hardware-Upgrade
Mit sauberem Shaping schöpfe ich vorhandene Leitungen besser aus und spare häufig teure Upgrades. Weniger Paketverluste und geringere Latenz steigern die Nutzererfahrung direkt. In Hosting-Umgebungen zahlt sich das doppelt aus, weil faire Limits Eskalationen zwischen Mandanten verhindern. Ich sehe in der Praxis, dass stabile Raten den Durchsatz erhöhen, da Retransmits sinken. Diese Effekte schlagen sich am Ende in klareren SLAs und weniger Supportfällen nieder.
Häufige Stolperfallen und schnelle Checks
- Unpassende Einheiten: Ich prüfe, ob
mbitundkbitkorrekt geschrieben sind und Burst/Latency zur MTU passen. - Prioritätsumkehr: Zu viele High‑Priority‑Klassen ohne echte Begrenzung führen zu Starvation der Defaults. Ich halte Obergrenzen strikt ein.
- NAT/IPv6 übersehen: Port‑Filter greifen nach NAT/IPv6 nicht wie gedacht. Ich markiere früh (fwmark) und mappe dann in Klassen.
- Ceil kleiner als Rate: Ein häufiger Tippfehler, der Borrowing blockiert. Ich validiere jede Klasse mit
tc -s class. - Ingress nur gepolicet: Hartes Droppen erzeugt Jitter. Mit IFB forme ich feiner und gerechter.
- Offloads verfälschen Messung: Ich dokumentiere den Offload‑Zustand bei jedem Test und vergleiche Äpfel mit Äpfeln.
Zukunftsausblick: KI-gestützte Reservierung und adaptive Policies
Ich nutze Trends wie Vorhersagen auf Basis historischer Last, um Klassen kurz vor Peak-Zeiten dynamisch anzupassen. Lernende Modelle reservieren Bandbreite für VoIP- oder Checkout-Phasen, bevor Warteschlangen wachsen. In hybriden Netzen zwischen Cloud und On-Prem greife ich auf temporäre Caps und Burst-Budgets zurück, die Policies per Zeitplan wechseln. Das reduziert operative Eingriffe und hält Services auch bei Sonderevents berechenbar. Tieferes Hintergrundwissen zu Skalierung und Limits bündele ich hier: Traffic-Management und Hosting-Limits.
Kurzfassung & Checkliste
Ich setze zuerst eine klare Hierarchie mit HTB auf, vergebe Garantien und halte Ceil leicht unter Link-Speed. Danach klassifiziere ich nach Diensten, Protokollen oder DSCP und prüfe Latenz, Jitter sowie P95-Werte. SFQ oder FQ_CoDel sorge ich für faire Verteilung und kurze Queues. Monitoring begleitet jede Änderung, damit ich über Effekte entscheide statt zu raten. So bleibt Bandwidth Shaping kein einmaliger Akt, sondern ein schlanker Regelkreis, der Serververkehr sicher und kalkulierbar hält.


