27/07/2005
traffic shaping a dsl line with linux
The case is like this:
[code]
Internet < --> [dsl modem] < --> [linux box] < --> [Lan]
[/code]
DSL modem is connected on eth2 on linux box and the rest of the Lan on eth0. I had a serious problem with people leaving edonkey clients opens all night..limiting the download speed to 20kb/sec but forgetting to limit the upload. The current dsl line is 384/128 so having the uploads unlimited…is like killing the line.
The solution was to setup a QOS script. And here it is:
[code]
#!/bin/bash
DEV=”eth2″
LOCALIF=”eth2″
# Reset everything to a known state (cleared)
tc qdisc del dev $DEV root 2> /dev/null > /dev/null
tc qdisc del dev imq0 root 2> /dev/null > /dev/null
iptables -t mangle -F POSTROUTING 2> /dev/null > /dev/null
iptables -t mangle -Z POSTROUTING 2> /dev/null > /dev/null
iptables -t mangle -X POSTROUTING 2> /dev/null > /dev/null
iptables -t mangle -F tosfix
iptables -t mangle -F ack
ip link set imq0 down 2> /dev/null > /dev/null
rmmod imq 2> /dev/null > /dev/null
if [ “$1” = “stop” ]
then
echo “Shaping removed on $DEV.”
exit
fi
tc qdisc add dev $DEV root handle 1: tbf rate 85kbit burst 1600 limit 1
tc qdisc add dev $DEV parent 1:1 handle 2: prio bands 4
tc qdisc add dev $DEV parent 2:1 handle 10: sfq perturb 10
tc qdisc add dev $DEV parent 2:2 handle 20: sfq perturb 10
tc qdisc add dev $DEV parent 2:3 handle 30: sfq perturb 10
tc qdisc add dev $DEV parent 2:4 handle 40: tbf rate 40kbit burst 1600 limit 3000
tc qdisc add dev $DEV parent 40:1 handle 41: pfifo limit 10
iptables -t mangle -N tosfix
iptables -t mangle -A tosfix -p tcp -m length –length 0:64 -j RETURN
iptables -t mangle -A tosfix -m limit –limit 2/s –limit-burst 10 -j RETURN
iptables -t mangle -A tosfix -j TOS –set-tos Maximize-Throughput
iptables -t mangle -A tosfix -j RETURN
iptables -t mangle -N ack
iptables -t mangle -A ack -m tos ! –tos Normal-Service -j RETURN
iptables -t mangle -A ack -p tcp -m length –length 0:64 \
-j TOS –set-tos Minimize-Delay
iptables -t mangle -A ack -p tcp -m length –length 64: \
-j TOS –set-tos Maximize-Throughput
iptables -t mangle -A ack -j RETURN
# Is our TOS broken? Fix it for TCP ACK and OpenSSH.
iptables -t mangle -A POSTROUTING -p tcp -m tcp –tcp-flags SYN,RST,ACK ACK -j ack
iptables -t mangle -A POSTROUTING -p tcp -m tos –tos Minimize-Delay -j tosfix
# Here we deal with ACK, SYN, and RST packets
# Match SYN and RST packets
iptables -t mangle -A POSTROUTING -o $LOCALIF -p tcp -m tcp –tcp-flags ! SYN,RST,ACK ACK \
-j CLASSIFY –set-class 2:1
# Match ACK packets
iptables -t mangle -A POSTROUTING -o $LOCALIF -p tcp -m tcp –tcp-flags SYN,RST,ACK ACK \
-m length –length :128 -m tos –tos Minimize-Delay \
-j CLASSIFY –set-class 2:1
# Match packets with TOS Minimize-Delay
iptables -t mangle -A POSTROUTING -o $LOCALIF -p tcp -m tos –tos Minimize-Delay \
-j CLASSIFY –set-class 2:1
### Actual traffic shaping classifications with CLASSIFY
# ICMP (ping)
iptables -t mangle -A POSTROUTING -o $LOCALIF -p icmp -j CLASSIFY –set-class 2:1
# Outbound client requests for HTTP, IRC and AIM (dport matches)
iptables -t mangle -A POSTROUTING -o $LOCALIF -p tcp –dport 80 -j CLASSIFY –set-class 2:2
iptables -t mangle -A POSTROUTING -o $LOCALIF -p tcp –dport 6667 -j CLASSIFY –set-class 2:2
iptables -t mangle -A POSTROUTING -o $LOCALIF -p tcp –dport 5190 -j CLASSIFY –set-class 2:2
iptables -t mangle -A POSTROUTING -o $LOCALIF -p tcp –sport 80 -j CLASSIFY –set-class 2:3
iptables -t mangle -A POSTROUTING -o $LOCALIF -p tcp –dport 1024: -j CLASSIFY –set-class 2:4
[/code]
It WORKS for me…I don’t know whether it will work for you though. I take no responsibility. I will explain it no further because comments do exists and it’s really easy to understand what’s going on if you read a couple of tc tutorials from the net. Many ideas about this script were “stolen” from other scripts I studied while trying to make mine.
Have fun with it…
Here’s an mrtg graph to see how it’s working. Watch the blue line which is the uploads. It never goes beyond a reasonable limit and download stays unaffected:
Filed by kargig at 10:46 under General,Internet,Linux
2 Comments | 10,072 views
Nice post; I missed it previously, but I was googling for something similar and found this.
Hey, good job!
I’ve been recently writing a traffic shaper for my home network. I found you in Google when looking for information about matchink ACK packets with iptables.
What surprised me, is that if I match the ACK packets and send them to the interactive class, the interactive class gets overloaded. So I modified this rule to match the _small_ ACK packets. It looks like this:
iptables -t mangle -A MACIEJSHAPER -p tcp -m tcp –tcp-flags FIN,SYN,RST,ACK ACK -m length –length :64 -j MARK –set-mark 2
(I’m using MARK instead of CLASSIFY)
I don’t really know why the lots of ACK packets — in my case it’s up to 8kB/s, half of the 128kbit uplink bandwidth.