= Quality of Service =
* verteilt Bandbreite auf mehrere Beduerftige
* verbessert die Reaktionsfaehigkeit von ssh & co waehrend eines Downloads
* anscheinend verbessert es auch die Download-Geschwindigkeit waehrend eines Uploads, da die ''ack''-Pakete mit hoeherer Prioritaet rausgeschickt werden koennen
== !=Begriffstutzig ==
* Ethernet kennt kein "Quality-of-Service" (im Gegensatz zu z.B. ATM)
* aber: in Headern der versch. Protokollebenen lassen sich gezielt Bits setzen (zur Priorisierung)
* IP auf Ethernet kann Resourcen reservieren und Pakete priorisieren, dies wird meist "Class-of-Service" gennant
* Hardware muss damit allerdings umgehen koennen (spezielle Switches, Router)
* Linuxrechner als Router kann das (wie dieses QoSHowTo (eigentlich CoS) gut beschreibt)
* WLAN-AP kann das eher nicht
== Notwendigkeiten ==
* mindestens 2.4er-Kernel
* QoS und die anhaengigen Verfahren fest oder modular einbauen
* unter ''IP: Netfilter'' sollte ''tos-'', ''mark-'' und ''length-matching'', sowie das ''MARK-Target'' drin sein
* das iproute-Paket (debian-testing!)
* iptables
== Grundgedanken ==
* das Engpass-Device in Richtung Freiheit wird von mehreren Warteschlangen gefuettert
* die Warteschlangen erhalten unterschiedliche Prioritaeten oder Transfer-Limits
* anhand sinnvoller Kriterien werden die Pakete, die hinaus wollen, der passenden Warteschlange zugeordnet
* diese Zuordnung erfolgt in zwei Schritten:
* zuerst werden alle relevanten Pakete per ''iptables'' mit einer Prioritaetskennzahl markiert (''--mark X'')
* wenn sie nun das Ausgangs-Interface erreichen, schiebt iproute (also ''tc'') die Pakete einfach entsprechend dieser Markierung in die jeweilige Warteschlange
== Umsetzung ==
=== Pakete Sortieren ===
* eigentlich werden sie erstmal nur entsprechend ihrer Bedeutung markiert ...
{{{
iptables -t mangle -A OUTPUT -m length --length 0:500 -j MARK --set-mark 1
iptables -t mangle -A OUTPUT -m length --length 500:1500 -j MARK --set-mark 2
}}}
* diese Regel gilt fuer Verkehr, der im qos-Rechner erzeugt wurde
* bei der Weiterleitung durch einen Router saehe es so aus:
{{{
iptables -t mangle -A FORWARD -o $DEV -m length --length 0:500 -j MARK --set-mark 1
iptables -t mangle -A FORWARD -o $DEV -m length --length 500:1500 -j MARK --set-mark 2
}}}
* zusaetzlich zur Paketlaenge (kleine ssh- und ack-Pakete) koennen natuerlich auch andere Kriterien verwendet werden
{{{
iptables -t mangle -A FORWARD -o $DEV -m tos --tos 0x10 -j MARK --set-mark 1
}}}
* ''tos 0x10'' steht fuer ''minimize delay'' - also wahrscheinlich irgendwelche Streams
* oder die Herkunft eines Pakets kann wichtig sein:
{{{
iptables -t mangle -A FORWARD -o $DEV -s PRIVILEG_IP -j MARK --set-mark 1
}}}
* um einen Download bei gleichzeitigem Upload zu beschleunigen, sollten die ack-Pakete vorgeschickt werden:
{{{
iptables -t mangle -A FORWARD -o $DEV -p tcp --tcp-flags ACK ACK -j MARK --set-mark 1
}}}
* zum Testen und weil es gut aussieht - schnelles icmp:
{{{
iptables -t mangle -A FORWARD -o $DEV -p icmp -j MARK --set-mark 1
}}}
* anhand der Markierungen werden die Pakete dann auf die Warteschlangen verteilt
=== Warteschlangen konfigurieren ===
* ein Warteschlangensystem an das Device haengen
{{{
tc qdisc add dev $DEV root handle 1: htb default 20
}}}
* die default-Warteschlage ist die ''20''
* diese erste Warteschlange legt die oberste Grenze fest - sie sollte ein wenig unterhalb der theoretischen Bandbreite liegen, damit die Warteschlange beim ISP nicht voll wird (sonst werden die von uns muehsam beschleunigten Pakete dort wieder ausgebremst)
{{{
tc class add dev $DEV parent 1: classid 1:1 htb rate ${UPLINK}kbit burst 6k
}}}
* nun werden Warteschlagen mit verschiedenen Prioritaeten und Bandbreitengrenzen angelegt
{{{
tc class add dev $DEV parent 1:1 classid 1:10 htb rate ${UPLINK}kbit burst 6k prio 1
tc class add dev $DEV parent 1:1 classid 1:20 htb rate ${UPLINK}kbit burst 6k prio 2
}}}
* beide erhalten stochastische Fairness - das heisst, dass gelegentlich die Warteschlange neu gemischt wird, damit keine der Sitzungen, die durch diese Schlange muessen, zu lange warten muss
{{{
tc qdisc add dev $DEV parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10
}}}
* nun wird das Kriterium fuer die Zuteilung der Pakete festgelegt
{{{
tc filter add dev $DEV parent 1: protocol ip handle 1 fw flowid 1:10
tc filter add dev $DEV parent 1: protocol ip handle 2 fw flowid 1:20
}}}
* ''ip handle X fw'' bezieht sich auf die Markierung, die vorher durch iptables an die Pakete gehaengt wurde
== kurz & fertig ==
* erstmal die Warteschlangen erzeugen
1. {{{
!/bin/sh
UPLINK=120
DOWNLINK=980
OUTDEV=eth0
}}}
1. bisherige Warteschlangen loeschen
{{{
tc qdisc del dev $OUTDEV root &>/dev/null
tc qdisc del dev $OUTDEV ingress &>/dev/null
}}}
1. neu anlegen
{{{
tc qdisc add dev $OUTDEV root handle 1: htb default 14
}}}
1. die Gesamtwarteschlange verhindert, dass die Queue des ISP voll wird
{{{
tc class add dev $OUTDEV parent 1: classid 1:1 htb rate ${UPLINK}kbit burst 6k
}}}
1. Warteschlangen erzeugen
{{{
tc class add dev $OUTDEV parent 1:1 classid 1:11 htb rate ${UPLINK}kbit burst 6k prio 1
}}}
1. fuer die wichtigen Pakete (ssh und ack)
{{{
tc class add dev $OUTDEV parent 1:1 classid 1:12 htb rate ${UPLINK}kbit burst 6k prio 2
}}}
1. das Labor-Netz
{{{
tc class add dev $OUTDEV parent 1:1 classid 1:13 htb rate ${UPLINK}kbit burst 6k prio 3
}}}
1. das WG-Netz
{{{
tc class add dev $OUTDEV parent 1:1 classid 1:14 htb rate ${UPLINK}kbit burst 6k prio 4
}}}
1. alle anderen da draussen
1. stochastische Fairness aktivieren, damit alle Sitzungen in einer Schlange "gut" durchkommen
{{{
tc qdisc add dev $OUTDEV parent 1:11 handle 11: sfq perturb 10
tc qdisc add dev $OUTDEV parent 1:12 handle 12: sfq perturb 10
tc qdisc add dev $OUTDEV parent 1:13 handle 13: sfq perturb 10
tc qdisc add dev $OUTDEV parent 1:14 handle 14: sfq perturb 10
}}}
1. die iptables-Markierungen zum Filtern verwenden
{{{
tc filter add dev $OUTDEV parent 1: protocol ip handle 1 fw flowid 1:11
tc filter add dev $OUTDEV parent 1: protocol ip handle 2 fw flowid 1:12
tc filter add dev $OUTDEV parent 1: protocol ip handle 3 fw flowid 1:13
tc filter add dev $OUTDEV parent 1: protocol ip handle 4 fw flowid 1:14
}}}
1. etwas verlangsamen, um die Queue beim ISP nicht zu fuellen
{{{
tc qdisc add dev $OUTDEV handle ffff: ingress
tc filter add dev $OUTDEV parent ffff: protocol ip prio 50 u32 match ip src 0.0.0.0/0 police rate $[DOWNLINK/2]kbit burst 1
0k drop flowid :1
}}}
* und dann die Pakete mit den Markierungen versehen:
1. die drei Quellen mit Prioritaten versehen
{{{
iptables -t mangle -A FORWARD -i $WLAN_LABOR -o $WORLD -s ! $THORAX -j MARK --set-mark 4
iptables -t mangle -A FORWARD -i $WG_NETZ -o $WORLD -j MARK --set-mark 3
iptables -t mangle -A FORWARD -i $WLAN_LABOR -o $WORLD -s $THORAX -j MARK --set-mark 2
}}}
1. die schnellen Pakete nach vorn schicken (vorherige Markierungen werden ueberschrieben)
{{{
iptables -t mangle -A FORWARD -o $WORLD -m length --length 0:500 -j MARK --set-mark 1
iptables -t mangle -A FORWARD -o $WORLD -m tos --tos 0x10 -j MARK --set-mark 1
iptables -t mangle -A FORWARD -o $WORLD -p icmp -j MARK --set-mark 1
iptables -t mangle -A FORWARD -o $WORLD -p tcp --tcp-flags ACK ACK -j MARK --set-mark 1
}}}
1. der Rest (nur um zu gucken, ob was uebrigbleibt)
{{{
iptables -t mangle -A FORWARD -o $WORLD -m mark --mark 0 -j MARK --set-mark 5
}}}
= Quellen =
* http://lartc.org/howto/lartc.cookbook.ultimate-tc.html
* http://www.prout.be/qos/QoS-connection-tuning-HOWTO-4.html