Traffic-Shaping

Aus wiki.freifunk.net
Zur Navigation springenZur Suche springen
Traffic-Shaping
Traffic Shaping
Developer
First released
Latest preview version
Release date and age
Frequently updated yes
Programming language
Platform Gnu/Linux
Language Multilingual
Status active
Genre Skripte
License GNU General Public License, LGPL
Website
Download


Warum Trafficshaping?

Selbst mit hohem Zeitaufwand gelingt es einem Anschlussinhaber manuell kaum, die Vielzahl der Internetverbindungen derart zu regulieren, dass alle Teilnehmer den Dienst möglichst reibungsfrei nutzen können. Ein Skript kann hier helfen. Das einzige, was man wirklich sinnvoll beeinflussen kann, ist der ausgehende Verkehr - eingehender Verkehr besteht ja zumindest hier meist aus Antworten auf gemachte Anfragen, deren Größe vorher nicht absehbar ist. Diesen ausgehenden Verkehr so zu gestalten, dass der Anschluss trotz heftiger Benutzung für alle nutzbar bleibt, ist die Aufgabe dieses Skriptes.

  • Anlaß zum Schreiben waren - außer purem Eigeninteresse ;) - auch die Vorteile des Trafficshapings auf dem Internetgateway:
    • das FF-Netz ist im Idealfall viel schneller als ein DSL-Zugang, vor allem was den Upstream betrifft - der beträgt bei DSL nur ca. 1/8 des Downstreams (1 Mbit down = 128 kbit up)
    • daraus resultiert häufig eine "Verstopfung" des Upstreams, die bereits durch einen einzigen Nutzer leicht verursacht werden kann
    • diese Verstopfung der Sendewarteschlange führt zu (vielen) verworfenen und somit neu zu sendenden Paketen - die Latenz steigt - es fühlt sich zäh an
    • die Sendewarteschlange bildet sich im DSL-Modem, wo man sie nicht kontrollieren kann
    • die logische Folgerung ist: den Verkehr schon im Gateway-Router so zu gestalten, dass eine Überfüllung der Sendewarteschlange im Modem vermieden wird
    • das nennt sich Trafficshaping und wird nicht durch einfache Bandbreitenbegrenzung erreicht, sondern durch verschiedene Arten der Neuanordnung der abgehenden Datenpakete

Features

  • der Hauptzweck dieser Skripte besteht darin, den Einfluß hohen Verkehrsaufkommens allgemein und der Nutzung von Filesharing-Programmen im besonderen auf die Gesamtperformance des Internet-Anschlusses so gering wie möglich zu halten und dabei gleich noch den normalen Verkehr zu "verflüssigen".
  • Priorisierung der Pakete einzelner Klienten oder ganzer Subnetze nach:
    • dem Inhalt - Stichwort P2P - siehe oben
    • dem TOS (Type of Service), den jedes Paket hat - der so etwas wie die Wichtigkeit im Vergleich zu anderen darstellt
    • der Größe der Pakete - ACK-Pakete (Bestätigung) z. B. sind meist klein - und deren schneller Transport wichtig für eine flüssige Verbindung
    • der Verbindung, zu der die Pakete gehören


Mein (Jochen) reality-check hat ergeben, dass sich diese Skripte sehr gut machen!
(Aus eigener Erfahrung kann ich das nur von dem ersten - von meinem - sagen. Das zweite ist aber auch schon lange bei einigen Leuten im Einsatz und tut seine Aufgabe gut, wie ich höre.)
Der Verkehr auch unter hoher Netzlast ist flüssiger und Beeinträchtigungen durch Leute, die das Filesharen nicht lassen können, halten sich in akzeptablen Grenzen, da diese Art von Verkehr mittels dieses Scriptes immer als letztes bedient wird.

Hier wird also nichts gesperrt oder verworfen - wer das möchte oder braucht kann das aber leicht anpassen.

Bitte immer mal nachschauen, ob die Version aktuell ist - ich bastele immer mal noch ein bischen die alten Versionen findet man ja dank Wiki auch immer noch

aktualisiert am: 07.04.2008

  • nochmal völlig überarbeitetes Skript - habe die Bandbreitenregelung mittels HTB verworfen und statt dessen auf PRIO gebaut weil mein Internetanschluß bei MaxxOnAir eine ständig so stark schwankende Bandbreite hat, daß das auf einer festen Bandbreite basierende HTB völlig fehl am Platze war.
    Zwischen 4kBit und 400kBit upstream ist hier alles drin :/

Bei einem DSL-Anschluß mit fester Bandbreite ist HTB eher das Mittel der Wahl.

Jochens Version

Pakete/Module installieren

Um das Skript nutzen zu können, wird ein neues "tc" gebraucht. Bei dem in der Firmware Vorhandenen handelt es sich um eine abgespeckte Version, welche die benötigten Kommandos nicht unterstützt.

Die Installationsschritte zum Copy & Paste:

ipkg update
ipkg install tc
ipkg install iptables-mod-filter
ipkg install iptables-mod-conntrack
ipkg install iptables-mod-ipopt
ipkg install iptables-extra
ipkg install freifunk-openwrt-compat

Die Installation dauert lange. Nicht gleich verzweifeln, wenn die Konsole scheinbar hängen sollte!

  • ACHTUNG!
    • die Variable für das WAN-Interface (NETDEVICE) muß ggf. angepaßt werden!
    • das Script sollte vor dem runterfahren des WAN-Interfaces gestoppt werden - die Warteschlangen existieren nicht mehr, wenn das Interface aus irgendeinem Grund nicht mehr da ist
    • auf jeden Fall muß das Script neu gestartet werden, wenn das WAN aus irgendeinem Grund neu gestartet wurde (ist hier bei MaxxOnAir keine Seltenheit)
      die "status" und/oder "restart"-Funktion kann dazu benutzt werden.

Skript anlegen

Unter /etc/init.d/ eine neue Datei z.B. namens S92prioritize mit z. B. WinSCP anlegen und folgenden Inhalt einfügen:

#!/bin/sh

### Version 0.4 - 07.04.2008 ####
#
# kleine Korrekturen und erweiterte Funktionalität: u.a Statusabfrage durch externe Programme möglich
#
# bei Version 0.3 nochmal völlig ueberarbeitete Version
# nun nur mit "prio" statt mit "htb"
# htb setzt eine feste Bandbreite voraus um korrekt zu funktionieren
# und war deshalb ungeeignet fuer meinen MaxxOnAir Zugang mit *staendig* *sehr* *stark* schwankender Bandbreite
# von 5kBit bis 500kBit upstream ist hier alles moeglich :/
#
# vielen Dank auch an Björn, von dem ich einiges übernommen hab
#


test -n "$FAILSAFE" && exit

ME="${0##*/}"
TC=`which tc 2> /dev/null`
TC_ORIG="/rom/usr/sbin/tc"
IPTABLES=`which iptables 2> /dev/null`
IPT="$IPTABLES -t mangle"

# welches ist das WAN-Interface ?
NETDEVICE=ppp0

# die benötigten Module laden
INSMOD=`which insmod 2> /dev/null`
LSMOD=`which lsmod 2> /dev/null`
GREP=`which grep 2> /dev/null`
RMMOD=`which rmmod 2> /dev/null`

load_modules() {

	for i in "cls_fw" "ipt_CONNMARK" "ipt_connmark" "ipt_conntrack" "ipt_layer7" "ipt_length" "ipt_tos"
	do
		if [ -z "`$LSMOD | $GREP $i`" ]; then
			$INSMOD "$i" > /dev/null 2>&1

		elif [ -n "`$LSMOD | $GREP $i`" ]; then
			echo "module ($i) was already loaded"

		else
			logger -s -t "$ME" "module ($i) was not loaded - THIS IS NOT GOING TO WORK"
			echo "!!! ERROR !!!"			
			echo "module ($i) was not loaded - exiting"
			exit
		fi
	done
}

unload_modules() {

	for i in "cls_fw" "ipt_CONNMARK" "ipt_connmark" "ipt_conntrack" "ipt_layer7" "ipt_length" "ipt_tos"
	do
		if [ -n "`$LSMOD | $GREP $i`" ]; then
			$RMMOD "$i" > /dev/null 2>&1
#		else
#			logger -s -t "$ME" "module ($i) was not unloaded - not a problem"
#			echo "!!! ERROR !!!"
#			echo "module ($i) was not unloaded - exiting"
#			exit
		fi
	done
}


setup_prio() {

PRIO_1="11"
PRIO_2="12"
PRIO_3="13"

PRIO_4="14"
PRIO_5="15"
PRIO_6="16"


# die Ketten anlegen und leeren
	$IPT -N track
	$IPT -F track
	$IPT -N protomatch
	$IPT -F protomatch
	$IPT -N packetsize
	$IPT -F packetsize
	$IPT -N typeofservice
	$IPT -F typeofservice
	$IPT -N markit
	$IPT -F markit
	$IPT -N split
	$IPT -F split
	$IPT -N higher_prio
	$IPT -F higher_prio

# hänge sie in die POSTROUTING mangle Kette
	$IPT -A POSTROUTING -j track
	$IPT -A POSTROUTING -j protomatch
	$IPT -A POSTROUTING -j typeofservice
	$IPT -A POSTROUTING -j markit
	$IPT -A POSTROUTING -j packetsize
	$IPT -A POSTROUTING -j split
	$IPT -A split -j higher_prio

# stelle eine vorhandene Verbindungs-Markierung wieder her
# hier ist auch schon Schluß für Pakete, die schon eine haben
	$IPT -A track -p tcp -j CONNMARK --restore-mark
	$IPT -A track -m mark --mark $PRIO_3 -j ACCEPT
	$IPT -A track -m mark --mark $PRIO_6 -j ACCEPT

# es war keine Verbindungs-Markierung da - prüfe jedes Paket auf jedes der Muster
# sobald es passt springe zu "markit" um die Verbindungs-Markierung zu setzen
	$IPT -A protomatch -m layer7 --l7proto fasttrack -j MARK --set-mark $PRIO_6
	$IPT -A protomatch -m mark --mark $PRIO_6 -j markit

	$IPT -A protomatch -m layer7 --l7proto edonkey -j MARK --set-mark $PRIO_6
	$IPT -A protomatch -m mark --mark $PRIO_6 -j markit

	$IPT -A protomatch -m layer7 --l7proto edonkey-dl -j MARK --set-mark $PRIO_6
	$IPT -A protomatch -m mark --mark $PRIO_6 -j markit

	$IPT -A protomatch -m layer7 --l7proto bittorrent -j MARK --set-mark $PRIO_6
	$IPT -A protomatch -m mark --mark $PRIO_6 -j markit

	$IPT -A protomatch -m layer7 --l7proto gnutella -j MARK --set-mark $PRIO_6
	$IPT -A protomatch -m mark --mark $PRIO_6 -j markit

# es hat auch kein Muster gepasst bisher - nun sehen wir und das TOS an
# wenn das passt springe zu "markit" um die Verbindungs-Markierung zu setzen
	$IPT -A typeofservice -m tos --tos Minimize-Delay -j MARK --set-mark $PRIO_4
	$IPT -A typeofservice -m tos --tos Maximize-Throughput -j MARK --set-mark $PRIO_5
	$IPT -A typeofservice -m mark --mark $PRIO_4 -j markit
	$IPT -A typeofservice -m mark --mark $PRIO_5 -j markit

# markiere die ganze Verbindung - dann springe zu "split"
	$IPT -A markit -j CONNMARK --save-mark
	$IPT -A markit -j split

# hier kommen Pakete an, auf die bis jetzt noch keine Regel gepasst hat
# markiere diese anhand ihrer Größe - dann springe zu "split"
	$IPT -A packetsize -m length --length 0:128 -j MARK --set-mark $PRIO_4
	$IPT -A packetsize -m length --length 129: -j MARK --set-mark $PRIO_5
	$IPT -A packetsize -m mark --mark $PRIO_4 -j split
	$IPT -A packetsize -m mark --mark $PRIO_5 -j split

# lege anhand der Netzwerkaddresse fest, wessen Pakete eine höhere Priorität erhalten sollen
# Du selbst und möglicherweise Nachbarn oder Freunde kommen hier hin
# jeder in eine Zeile - ganze Subnetze (z.B. 10.0.0.0/24) auch möglich
	$IPT -A split -s 192.168.1.17 -j higher_prio
	$IPT -A split -s 104.61.114.17 -j higher_prio

	$IPT -A higher_prio -m mark --mark $PRIO_4 -j MARK --set-mark $PRIO_1
	$IPT -A higher_prio -m mark --mark $PRIO_5 -j MARK --set-mark $PRIO_2
	$IPT -A higher_prio -m mark --mark $PRIO_6 -j MARK --set-mark $PRIO_3

# hier kommen die Warteschlangen um den Verkehr anhand der vorher gesetzten fw-Markierungen zu priorisieren
# es wird hier kein kein Bandbreitenmanagement gemacht - nur anhand der Paketeigenschaften priorisiert
# für echtes DSL (MaxxOnAir fällt da nicht drunter) wäre es anders (mit "htb") sicher besser
# hier hab ich aber einen Zugang von MaxxOnAir mit ständig stark schwankender Bandbreite - "htb" war also völlig ungeeignet, da es eine fixe Bandbreite vorraussetzt
# 6 Bänder von 0 bis 5 zum priorisieren
# per Voreinstellung geht erstmal alles nach Band 5 - also das sechste - mit der niedrigsten Priorität
	$TC qdisc add dev $NETDEVICE root handle 1: prio bands 6 priomap 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5

	$TC qdisc add dev $NETDEVICE parent 1:1 sfq perturb 10
	$TC qdisc add dev $NETDEVICE parent 1:2 sfq perturb 10
	$TC qdisc add dev $NETDEVICE parent 1:3 sfq perturb 10
	$TC qdisc add dev $NETDEVICE parent 1:4 sfq perturb 10
	$TC qdisc add dev $NETDEVICE parent 1:5 sfq perturb 10
	$TC qdisc add dev $NETDEVICE parent 1:6 sfq perturb 10
# in der letzten Zeile hier wär der Platz um eine htb Warteschlange statt der sfq einzufügen 
# um die Rate des Verkehrs durch Band 1:6 zu beschränken - das ist fast nur filesharing
# wenn es nötig wird mach ich das noch

# das sind die Filter die die Pakete den Warteschlangen zuordnen - basierend auf der Markierung, die oben erfolgte
# 6 Prioritäten - die ersten 3 sind für Pakete aus der  "higher_prio" Kette und werden allem anderen rigoros vorgezogen
# auf die Weise merkt der Eigentümer praktisch nichts davon, dass er seine Leitung mit wer weiss wie vielen anderen teilt ;)
	$TC filter add dev $NETDEVICE parent 1: protocol ip prio 1 handle $PRIO_1 fw flowid 1:1
	$TC filter add dev $NETDEVICE parent 1: protocol ip prio 2 handle $PRIO_2 fw flowid 1:2
	$TC filter add dev $NETDEVICE parent 1: protocol ip prio 3 handle $PRIO_3 fw flowid 1:3
	$TC filter add dev $NETDEVICE parent 1: protocol ip prio 4 handle $PRIO_4 fw flowid 1:4
	$TC filter add dev $NETDEVICE parent 1: protocol ip prio 5 handle $PRIO_5 fw flowid 1:5
	$TC filter add dev $NETDEVICE parent 1: protocol ip prio 6 handle $PRIO_6 fw flowid 1:6

}


stop_prio() {

# alles wieder abbauen - zuerst die Warteschlange löschen
$TC qdisc del dev $NETDEVICE root handle 1: prio

# dann die Ketten aushängen
	$IPT -D split -j higher_prio
	$IPT -D POSTROUTING -j split
	$IPT -D POSTROUTING -j packetsize
	$IPT -D POSTROUTING -j markit
	$IPT -D POSTROUTING -j typeofservice
	$IPT -D POSTROUTING -j protomatch
	$IPT -D POSTROUTING -j track

# leeren
	$IPT -F higher_prio
	$IPT -F split
	$IPT -F packetsize
	$IPT -F markit
	$IPT -F typeofservice
	$IPT -F protomatch
	$IPT -F track

#und löschen
	$IPT -X higher_prio
	$IPT -X split
	$IPT -X packetsize
	$IPT -X markit
	$IPT -X typeofservice
	$IPT -X protomatch
	$IPT -X track

}

# status feststellen: 0 --> nicht aktiv | 1 --> aktiv
get_status() {
		if [ -z "$($TC_ORIG qdisc show dev ppp0 2> /dev/null | grep prio)" ]; then
			exit 0
		else
			exit 1
		fi
}


# wird mit "show" aufgerufen - zeigt die Tabelle mit den Ketten und aktuellen Werten
list_table() {
	$IPT -nvL
}


case $1 in
	start)
		$0 status
		if [ "$?" -eq 0 ]; then
		logger -s -t "$ME" "starting to prioritize traffic through $NETDEVICE"
		echo "starte priorisierung"
		load_modules
		setup_prio
		echo "fertig! - Anzeigen der angelegten Regeln mit \"_scriptname_ show\""
		fi
	;;
	stop)
		$0 status
		if [ "$?" -eq 1 ]; then
		logger -s -t "$ME" "ceased prioritizing traffic through $NETDEVICE"
		echo "stoppe priorisierung"
		stop_prio
		unload_modules
		fi
	;;
	show)
		list_table
	;;
	status)
		get_status
	;;
	restart)
	$0 stop
	$0 start
	;;
	*)
	echo "Usage: $0 start|stop|show|restart"
	;;
esac

Nun das Skript speichern und ihm Rechte zum Ausführen geben. Mit

/etc/init.d/S92prioritize start

kann es manuell gestartet werden, ansonsten wird es automatisch beim Starten des Routers ausgeführt.

Kontrolle

Beim Ausführen des Skripts wird die Warteschlangen mangle eingerichtet. Wenn das Skript funktioniert, kann es mit

/etc/init.d/S92prioritize show

aufgerufen werden.

iptables -t mangle -nvL

ergibt dieselbe Ausgabe Damit kann überprüft werden, ob die Firewallregeln angelegt wurden und was aktuell für Verkehr durch welche der Ketten fließt.

Zudem lässt sich mit dem originalen tc-Paket, das auch jetzt noch im ROM (Firmware) verfügbar ist, mit:

/rom/usr/sbin/tc qdisc show

überprüfen, ob Einträge der Form

qdisc sfq 8018: dev vlan1 quantum 1518b perturb 10sec

erstellt wurden. Ist dies nicht der Fall, funktioniert das Skript nicht richtig.

Björns Version

#!/bin/sh

################ Version 0.3 - 29.09.2007 ################
#
# based on Jochen E.'s TC-Skript --> special THANKS!!!
#
# bei 5 Rauten(#####) müssen/ können Werte angepasst werden
#
# Iptables Module benötigt
#
# Trafficshaping: ipkg install tc
# l7-filter: ipkg install iptables-mod-filter
# TOS & Length: ipkg install iptables-mod-ipopt

if [ "$FAILSAFE" ]
  then
     exit
fi

PATH=/bin:/usr/bin:/sbin:/usr/sbin

TC=`which tc 2> /dev/null`               || TC="tc"
TCORIG="/rom/usr/sbin/tc"
IPTABLES=`which iptables 2> /dev/null`   || IPTABLES="iptables"
GREP=`which grep 2> /dev/null`           || GREP="grep"
INSMOD=`which insmod 2> /dev/null`       || INSMOD="insmod"
LSMOD=`which lsmod 2> /dev/null`         || LSMOD="lsmod"
AWK=`which awk 2> /dev/null`             || AWK="awk"
IP=`which ip 2> /dev/null`               || IP="ip"

for i in "$TC" "$IPTABLES" "$GREP" "$INSMOD" "$LSMOD" "$AWK" "$IP"
  do
     [ -x "$i" ] || { echo "'$i' not found - exiting"; exit 5; }
  done

#if [ -z "$(nvram get ff_gw_ext_if)" ]
#   then
#      echo "No external interface specified - exiting."
#      exit
#fi

eval $(/usr/bin/netparam)


##### externes WAN Device z.B. vlan1
#UPDEV="$(nvram get ff_gw_ext_if)"
UPDEV="vlan1"
#UPDEV=$WANDEV


##### Geschwindigkeiten
##### Upload-Geschwindigkeit des Internetanschlusses (kbit)
#     etwas unterhalb der Maximalgrenze z.B. anstatt 128 nur 120 verwenden
#     oder anstatt 384 nur 372 verwenden
#     >>> sollte ein Vielfaches von 12 sein <<<
UPRATE=180


##### Upload-Geschwindigkeit für LAN-/ highprio Benutzer reservieren, wenn Bedarf vorhanden (kbit)
#     >>> sollte ein Vielfaches von 12 sein <<<
UPRATEPRIO1=120

# Burst - kurzzeitige Ueberschreitung der max. Uprate
#
BURST=128


install_ts() {
# Überprüfung auf Existenz fundamentaler tc/ iptables Module
	for i in "sch_htb" "ipt_tos" "ipt_length" "cls_fw" "ipt_layer7"
	do
		$INSMOD "$i" > /dev/null 2>&1
		if [ -z "`$LSMOD | $GREP $i`" ]
			then
				echo "failed!"
				echo "tc/ iptables modul ($i) could not be loaded -aborting"
				exit
		fi
	done


# die Chains anlegen und leeren
	$IPTABLES -t mangle -N priomatch
	$IPTABLES -t mangle -F priomatch
	$IPTABLES -t mangle -N split
	$IPTABLES -t mangle -F split
	$IPTABLES -t mangle -N highprio
	$IPTABLES -t mangle -F highprio
	$IPTABLES -t mangle -N lowprio
	$IPTABLES -t mangle -F lowprio


# Kette priomatch anhängen 
	$IPTABLES -t mangle -A POSTROUTING -o $UPDEV -j priomatch


##### welche Dienste sollen priorisiert werden
# ---> hier können weitere Dienste hinzugefügt werden
# TCP-SYN Pakete
	$IPTABLES -t mangle -A priomatch -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -j MARK --set-mark 13
# TCP-ACK Pakete 40Byte oder 52Bytes mit Timestamp
	$IPTABLES -t mangle -A priomatch -p tcp -m tcp --tcp-flags ACK ACK -m length --length 40:52 -j MARK --set-mark 13
# TCP-Verbindungsabbruch/-ablehnung
	$IPTABLES -t mangle -A priomatch -p tcp -m tcp --tcp-flags RST RST -m length --length 40 -j MARK --set-mark 13
# TCP-Verbindungsbeendigung
	$IPTABLES -t mangle -A priomatch -p tcp -m tcp --tcp-flags FIN FIN -m length --length 40:52 -j MARK --set-mark 13
# TOS minimale Verzögerung - sinnvoll? Missbrauch? TODO
#	$IPTABLES -t mangle -A priomatch -m tos --tos Minimize-Delay -j MARK --set-mark 13
# DNS
	$IPTABLES -t mangle -A priomatch -p udp --dport 53 -j MARK --set-mark 13
# Zeitstellung (time, ntp)
	$IPTABLES -t mangle -A priomatch -p tcp --dport 37 -j MARK --set-mark 13
	$IPTABLES -t mangle -A priomatch -p udp --dport 123 -j MARK --set-mark 13
# SSH für kleine Pakete (kein SCP)
	$IPTABLES -t mangle -A priomatch -p tcp --dport 22 -m length --length :128 -j MARK --set-mark 13
# Unreal Tournament - lieber über l7-filter??? TODO
#	$IPTABLES -t mangle -A priomatch -p udp --dport 7777:7778 -j MARK --set-mark 13
# Teamspeak (teamspeak.pat)
#	$IPTABLES -t mangle -A priomatch -m layer7 --l7proto teamspeak -j MARK --set-mark 13
# IRC (irc.pat)
#	$IPTABLES -t mangle -A priomatch -m layer7 --l7proto irc -j MARK --set-mark 13
# ICQ
	$IPTABLES -t mangle -A priomatch -p tcp --dport 5190 -j MARK --set-mark 13
# Quake 1/ Halflife
#	$IPTABLES -t mangle -A priomatch -m layer7 --l7proto quake-halflife -j MARK --set-mark 13
# ICMP - auch ICMP priorisieren??? - ping spiegelt nicht richtiges Antwortverhalten wieder TODO
	$IPTABLES -t mangle -A priomatch -p icmp -j MARK --set-mark 13


# Kette splitten, um einzelne Clients wie z.B. den des Anschlusseigners zu priorisieren
	$IPTABLES -t mangle -A POSTROUTING -o $UPDEV -j split


##### split fuer Clients, die hoeher priorisiert werden sollen als der Rest
# ---> hier können weitere IP/ Bereiche hinzugefügt werden
# Rechner die an LAN-Ports hängen (Anschlusseigner)
	$IPTABLES -t mangle -A split -s $LANNET/$LANPRE -j highprio
#	$IPTABLES -t mangle -A split -s 105.61.116.21 -j highprio
# Böser Junge, darf aber Leitung voll nutzen, wenn nicht anderweitig verwendet
	$IPTABLES -t mangle -A split -s 104.61.116.18 -j lowprio
	$IPTABLES -t mangle -A split -s 105.61.116.18 -j lowprio


# Chain highprio, in die nur geht, was oben definiert wurde
	$IPTABLES -t mangle -A highprio -m mark --mark 13 -j MARK --set-mark 11
	$IPTABLES -t mangle -A highprio -m mark --mark 11 -j RETURN
	$IPTABLES -t mangle -A highprio -j MARK --set-mark 12


# Chain lowprio, in die nur geht, was oben definiert wurde
	$IPTABLES -t mangle -A lowprio -j MARK --set-mark 14


### Klassen und Warteschlangen werden angelegt
	$TC qdisc add dev $UPDEV root handle 1:0 htb r2q 1 default 14
# Parentklasse
	$TC class add dev $UPDEV parent 1:0 classid 1:1 htb rate ${UPRATE}kbit

	$TC class add dev $UPDEV parent 1:1 classid 1:2 htb rate ${UPRATEPRIO1}kbit ceil ${UPRATE}kbit
	$TC class add dev $UPDEV parent 1:1 classid 1:3 htb rate $(($UPRATE-$UPRATEPRIO1))kbit ceil ${UPRATE}kbit
	$TC class add dev $UPDEV parent 1:2 classid 1:11 htb rate $(($UPRATEPRIO1-24))kbit ceil ${UPRATE}kbit prio 1
	$TC class add dev $UPDEV parent 1:2 classid 1:12 htb rate 24kbit ceil ${UPRATE}kbit prio 2
	$TC class add dev $UPDEV parent 1:3 classid 1:13 htb rate $(($UPRATE-$UPRATEPRIO1-24))kbit ceil ${UPRATE}kbit prio 1
	$TC class add dev $UPDEV parent 1:3 classid 1:14 htb rate 24kbit ceil ${UPRATE}kbit prio 2

	$TC qdisc add dev $UPDEV parent 1:11 sfq perturb 10
	$TC qdisc add dev $UPDEV parent 1:12 sfq perturb 10
	$TC qdisc add dev $UPDEV parent 1:13 sfq perturb 10
	$TC qdisc add dev $UPDEV parent 1:14 sfq perturb 10

# TC-Filter
# highprio IPs
	$TC filter add dev $UPDEV protocol ip parent 1:0 prio 1 handle 11 fw flowid 1:11
	$TC filter add dev $UPDEV protocol ip parent 1:0 prio 2 handle 12 fw flowid 1:12
# restliche (Freifunk)/ lowprio IPs
	$TC filter add dev $UPDEV protocol ip parent 1:0 prio 3 handle 13 fw flowid 1:13
	$TC filter add dev $UPDEV protocol ip parent 1:0 prio 4 handle 14 fw flowid 1:14
}

clear_ts() {
# das ganze Setup der Reihe nach wieder abbauen
	$TC qdisc del dev $UPDEV root > /dev/null 2>&1

	$IPTABLES -t mangle -D POSTROUTING -o $UPDEV -j priomatch > /dev/null 2>&1
	$IPTABLES -t mangle -F priomatch > /dev/null 2>&1
	$IPTABLES -t mangle -X priomatch > /dev/null 2>&1

	$IPTABLES -t mangle -D POSTROUTING -o $UPDEV -j split > /dev/null 2>&1
	$IPTABLES -t mangle -F split > /dev/null 2>&1
	$IPTABLES -t mangle -X split > /dev/null 2>&1

	$IPTABLES -t mangle -F highprio > /dev/null 2>&1
	$IPTABLES -t mangle -X highprio > /dev/null 2>&1

	$IPTABLES -t mangle -F lowprio > /dev/null 2>&1
	$IPTABLES -t mangle -X lowprio > /dev/null 2>&1
}

case $1 in
	start)
		echo -n "Starting traffic shaping ... "
		clear_ts
		install_ts
		echo "done."
	;;
	stop)
		echo -n "Stopping traffic shaping ... "
		clear_ts
		echo "done."
	;;
	restart)
		$0 stop
		$0 start
	;;
	show)
		$TCORIG -d qdisc ls dev $UPDEV
		$TCORIG -d filter ls dev $UPDEV
	;;
	install)
		echo -n "Installing necessary packages ... "
		ipkg install tc
		ipkg install iptables-mod-filter
		ipkg install iptables-mod-ipopt
		$0 start		
	;;

	*)
		echo "Usage: $0 install|start|restart|stop|show"
	;;
esac