Trafficshaping

Inhaltsverzeichnis

Einleitung

Trfafficshaping nutzt man, um besser die Reihenfolge und Bandbreite von Datenpaketen festzulegen.

Warum

Ich verwende Trafficshaping, um Bandbreite zu begrenzen, damit der Upload nicht vollgestopft wird. Außerdem priorisiere ich die sogenannten ACK-Pakete, d.h. sie dürfen als erstes raus.

Funktionsweise

Trafficshaping wird durch das Tool tc aus dem iproute2-Paket realisiert, womit man viele Kernelparameter böse treten kann ;-)

Installation

Linux (Debian)

Die Installation des Grundpakets erfolgt mit:

apt-get install iproute

(kein Schreibfehler, das Paket heißt wirklich iproute und nicht iproute2!)

Konfiguration

Theorie

Wieso eigentlich ein Bandbreitenmanagement? Kann man den Datenverkehr nicht einfach machen lassen? - Diese Antwort liefert eigentlich auch schon Radio Eriwan: Im Prinzip ja, aber...

Das Problem besonders bei (T-)DSL ist der asymetrische Internetzugang und vergleichsweise geringe Upload. Das TCP-Protokoll ist so konzipiert, daß es jedes am Ziel angekommene Paket bestätigt wissen will, ansonsten geht es davon aus, daß der Transfer nicht erfolgreich war und schickt es erneut ab. Kommt es häufiger vor, wird die Geschwindigkeit herabgesetzt, bis es fast keine Fehler/ausbleibenden Bestätigungen mehr gibt. Ab und zu wird versucht, wieder schneller zu senden. Und genau hier liegt das Problem: Wenn der Upload vollgestopft ist (z.B. durch einen FTP-Upload, Esel, ...), müssen sich diese Bestätigungspakete eines Downloads ebenfalls in den dichten Upload einsortieren, der Gegenserver kriegt entsprechend später die Antwortpakete und wartet deshalb solange mit weiteren Transfers. Die Folge: Der Download bricht massiv ein.

Das in iproute2 enthaltene Tool tc verändert dazu die entsprechenden Kernel-Parameter. Es arbeitet (zumindest bei Einsatz von HTB, eine Verbesserung von CBQ) auf Baumbasis. Wie genau, wird im folgenden erklärt.

schrittweise zum Trafficshaping-Skript

Dazu muß man wissen, daß an oberster Stelle der sogenannte Root-Baum ist, der das Gerät (z.B. ppp0) enthält sowie diverse Optionen (wohin sollen Pakete gehen, wenn sie keinem Kriterium entsprechen?):

tc add qdisc dev ppp0 root handle 1: htb default 12

Es wird also ein Rootbaum für das Gerät ppp0 mit der Bezeichnung 1: angelegt. Pakete, die nicht markiert sind, landen in der Klasse 12 (siehe unten).

Dann folgt eine Grundklassifizierung, wie Grundbandbreite:

tc class add dev ppp0 parent 1: classid 1:1 htb rate 125kbit ceil 125kbit

Hier wird also davon ausgegangen, daß man einen DSL-Anschluß mit 128kbit Uploadrate hat. Man soll immer ein wenig unter den Maximalwert arbeiten, damit das Shaping im Extremfall noch hinterherkommt! Hier also etwa 125kbit. Natürlich besteht die Differenz nicht grundsätzlich 3kbit, gerade bei höheren Uploadraten muß man auch entsprechend die Differenz erhöhen. Diese Klasse wird also an den Rootbaum 1: angehängt, der Klassenbaum an sich beginnt mit 1:1.

Jetzt werden die Unterklassen zum Einsortieren der IP-Pakete festgelegt:

tc class add dev ppp0 parent 1:1 classid 1:10 htb rate 10kbit ceil 125kbit prio 0

Es wird an der Hauptklasse 1:1 ein Baum mit der Bezeichnung 1:10 rangehängt, die Mindestbandbreite ist 10kbit, die Maximalbandbreite 125kbit. Die Priorität gibt an, welchem Zweig der Kernel zunächst eine höhere Bandbreite als "rate" geben soll, wenn mehr benötigt wird (bis maximal "ceil"). Dabei gilt, je niedriger die prio, desto eher kommt dieser Zweig dran.

Machen wir noch entsprechend zwei weitere Regeln:

tc class add dev ppp0 parent 1:1 classid 1:11 htb rate 30kbit ceil 125kbit prio 1
tc class add dev ppp0 parent 1:1 classid 1:12 htb rate 85kbit ceil 125kbit prio 2

Hierbei gilt, daß die einzelnen rates in der Summe der rate der Hauptklasse entsprechen muß; die ceils dürfen den ceil der Hauptklasse nicht übersteigen.

Jetzt müssen wir noch sagen, welche markierten Paket in welche Unterklasse einsortiert werden müssen. Das machen wir am besten mit:

tc filter add dev ppp0 parent 1:0 prio 0 protocol ip handle 10 fw flowid 1:10

Hier werden also IP-Pakete mit der Markierung 10 in die Unterklasse 1:10 einsortiert.

tc filter add dev ppp0 parent 1:0 prio 0 protocol ip handle 11 fw flowid 1:11

Wie wir sehen, erfolgt die Einsortierung mit gleicher Priorität. Das soll sie auch, denn wir wollen ja bei der Filterung eine Gleichbehandlung.

Für die Regel 12 brauchen wir keine explizite Filterregel, weil da schon standardmäßig nichtmarkierte Pakete landen.


So schön das ganze nun aussieht, aber einen "Schönheitsfehler" gibt es noch: Wenn man in einem Netzwerk ist, haben Leute mit 100Mbit immer einen erheblichen Vorteil gegenüber 10Mbit-Leuten. Um allen Usern gleiche Chancen zu bieten, in den Upload zu geraten, richten wir noch eine sogenannte "Stochastic Fair Queue" ein:

tc qdisc add dev ppp0 parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev ppp0 parent 1:11 handle 11: sfq perturb 10
tc qdisc add dev ppp0 parent 1:12 handle 12: sfq perturb 10


Was ganz besonders ärgerlich ist, ist die Tatsache, daß die mühsam aufgebauten Trafficshapingregeln verfallen, sobald das Gerät verschwindet, z.B. durch den 24-Stunden-Disconnect. Deshalb empfiehlt es sich, das ganze in ein Skript zu packen und mittels chmod ausführbar zu machen.

Das Skript sollte wie folgt einleiten:

#!/bin/bash
if [ -n "`tc qdisc show dev ppp0`" ]
then
    tc qdisc del dev ppp0 root
fi

Das ganze ist eine Sicherheitsmaßnahme; falls das Gerät aus irgendeinem Grund doch noch existiert, wird vorsorglich vorher noch der Rootbaum "gekappt", alle darunterliegenden Regeln verschwinden automatisch.

Danach kommt dann das folgende nacheinander, was ich in diesem Kapitel beschrieben habe.

Damit das Skript nun nach jeder Einwahl gestartet wird, sollte das in /etc/ppp/ip-up.d/ abgelegt werden.

Markierung der Pakete

Ich hab im vorigen Kapitel immer von markierten Paketen gesprochen, die dann einsortiert werden. Wie markiert man denn überhaupt Pakete?

Dazu nehmen wir den Befehl iptables, den wir auch bereits beim Aufbau einer Firewall kennengelernt haben:

iptables -A POSTROUTING -t mangle -o ppp0 -p tcp -m length --length :64 -j MARK --set-mark 10

Hiermit werden also alle ACK-Pakete (TCP-Paketgröße bis max. 64 Bytes) mit dem Flag 10 markiert.

Das noch offene Flag 11 hab ich bei mir dazu benutzt, um SSH zu beschleunigen, damit ich nicht sekundenlang auf Reaktionen von Tastatureingaben warten muß *g*:

iptables -A POSTROUTING -t mangle -o ppp0 -p tcp --dport 22 -j MARK --set-mark 11

Also wie man sieht, kann man quasi nach alles und mögliche filtern. Wenn man will, auch nach IPs oder anderen Diensten. Man kann auch Unterbäume nochmal unterteilen, wenn man das wirklich will (z.B. der erste Unterbaum filtert nach IPs, der darunterliegende dann nach Diensten/Ports).

Achso, den reinkommenden Traffic kann man kaum regeln, da die Reihenfolge der zu mir versandten Pakete von dem Router vor mir - also der Vermittlungsstelle - bestimmt wird.


HINWEIS an iptables-Skripter: Man sollte direkt unterhalb der "iptables -F"-Befehle den Befehl

iptables -t mangle -F

aufnehmen, damit auch die Markierungsbefehle nicht doppelt angelegt bzw. bei Neuaufruf des Skriptes vorher gelöscht werden.

Von "http://lug-wr.de/wiki/index.php/Trafficshaping"

Diese Seite wurde bisher 10333 mal abgerufen. Diese Seite wurde zuletzt geändert um 12:08, 1. Mär 2006. Inhalt ist verfügbar unter der GNU Free Documentation License 1.2.