-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 1a1631d
Showing
2 changed files
with
218 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
HFSC traffic shaping helper script |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
#!/bin/bash | ||
# encoding: UTF-8 | ||
# | ||
# Maciej Bliziński, http://automatthias.wordpress.com/ | ||
# | ||
# References: | ||
# http://www.voip-info.org/wiki/view/QoS+Linux+with+HFSC | ||
# http://www.nslu2-linux.org/wiki/HowTo/EnableTrafficShaping | ||
# http://www.cs.cmu.edu/~hzhang/HFSC/main.html | ||
|
||
# Specify parameters of your xDSL. Give values slightly lower than the | ||
# nominal ones. For example, my line is 256/128, so I specify 240/100. | ||
|
||
# Uplink and downlink speeds | ||
DOWNLINK=$3 | ||
UPLINK=$4 | ||
|
||
# Device that connects you to the Internet | ||
DEV=$2 | ||
|
||
# Action to be performed | ||
ACTION=$1 | ||
|
||
# IP addresses of the VoIP phones, | ||
# if none, set VOIPIPS="" | ||
VOIPIPS="" | ||
|
||
# Interactive class: SSH Terminal, DNS and gaming (Quake) | ||
INTERACTIVEPORTS="22 23 53 3389 5900" | ||
|
||
# VoIP telephony | ||
#VOIPPORTS="5060:5100 10000:11000 5000:5059 8000:8016 5004 1720 1731" | ||
VOIPPORTS="" | ||
|
||
# WWW, jabber and IRC | ||
BROWSINGPORTS="80 443 8080" | ||
|
||
# The lowest priority traffic: eDonkey, Bittorrent, etc. | ||
P2PPORTS="110 25 21 143 445 137:139 4662 4664 6881:6999" | ||
|
||
######################################################################## | ||
# Configuration ends here | ||
######################################################################## | ||
|
||
function check_device() { | ||
if [ -z "$DEV" ] ; then | ||
echo "$0: stop requires a device, aborting." | ||
exit -1 | ||
fi | ||
} | ||
|
||
case "$ACTION" in | ||
status) | ||
check_device | ||
|
||
echo "[qdisc]" | ||
tc -s qdisc show dev $DEV | ||
|
||
echo "" | ||
echo "[class]" | ||
tc -s class show dev $DEV | ||
|
||
echo "" | ||
echo "[filter]" | ||
tc -s filter show dev $DEV | ||
|
||
echo "" | ||
echo "[iptables]" | ||
iptables -t mangle -L THESHAPER -v -x 2> /dev/null | ||
exit | ||
;; | ||
|
||
stop) | ||
check_device | ||
# Reset everything to a known state (cleared) | ||
tc qdisc del dev $DEV root > /dev/null 2>&1 | ||
tc qdisc del dev $DEV ingress > /dev/null 2>&1 | ||
|
||
# Flush and delete tables | ||
iptables -t mangle --delete POSTROUTING -o $DEV -j THESHAPER > /dev/null 2>&1 | ||
iptables -t mangle --flush THESHAPER 2> /dev/null > /dev/null | ||
iptables -t mangle --delete-chain THESHAPER 2> /dev/null > /dev/null | ||
echo "Shaping removed on $DEV." | ||
exit | ||
;; | ||
start) | ||
check_device | ||
if [ -z "$DOWNLINK" ] ; then | ||
echo "$0: start requires a downlink speed, aborting." | ||
exit -1 | ||
fi | ||
if [ -z "$UPLINK" ] ; then | ||
echo "$0: start requires an uplink speed, aborting." | ||
exit -1 | ||
fi | ||
|
||
# Traffic classes: | ||
# 1:2 Interactive (SSH, DNS, ACK, Quake) | ||
# 1:3 Low latency (VoIP) | ||
# 1:4 Browsing (HTTP, HTTPs) | ||
# 1:5 Default | ||
# 1:6 Low priority (p2p, pop3, smtp, etc) | ||
|
||
# add HFSC root qdisc | ||
tc qdisc add dev $DEV root handle 1: hfsc default 5 | ||
|
||
# add main rate limit class | ||
tc class add dev $DEV parent 1: classid 1:1 hfsc \ | ||
sc rate ${UPLINK}kbit ul rate ${UPLINK}kbit | ||
|
||
# Interactive traffic: guarantee realtime full uplink for 50ms, then | ||
# 5/10 of the uplink | ||
|
||
tc class add dev $DEV parent 1:1 classid 1:2 hfsc \ | ||
rt m1 ${UPLINK}kbit d 50ms m2 $((5*$UPLINK/10))kbit \ | ||
ls m1 ${UPLINK}kbit d 50ms m2 $((7*$UPLINK/10))kbit \ | ||
ul rate ${UPLINK}kbit | ||
|
||
# VoIP: guarantee full uplink for 200ms, then 3/10 | ||
tc class add dev $DEV parent 1:1 classid 1:3 hfsc \ | ||
sc m1 ${UPLINK}kbit d 200ms m2 $((3*$UPLINK/10))kbit \ | ||
ul rate ${UPLINK}kbit | ||
|
||
# Browsing: Don't guarantee anything for the first second, then | ||
# guarantee 1/10 | ||
|
||
tc class add dev $DEV parent 1:1 classid 1:4 hfsc \ | ||
sc m1 0 d 1s m2 $((1*$UPLINK/10))kbit \ | ||
ul rate ${UPLINK}kbit | ||
|
||
# Default traffic: don't guarantee anything for the first two seconds, | ||
# then guarantee 1/20 | ||
|
||
tc class add dev $DEV parent 1:1 classid 1:5 hfsc \ | ||
sc m1 0 d 2s m2 $((1*$UPLINK/20))kbit \ | ||
ul rate ${UPLINK}kbit | ||
|
||
# Default traffic: don't guarantee anything for the first 10 seconds, | ||
# then guarantee 1/20 | ||
|
||
tc class add dev $DEV parent 1:1 classid 1:6 hfsc \ | ||
sc m1 0 d 10s m2 $((1*$UPLINK/20))kbit \ | ||
ul rate ${UPLINK}kbit | ||
|
||
# add THESHAPER chain to the mangle table in iptables | ||
|
||
iptables -t mangle --new-chain THESHAPER | ||
iptables -t mangle --insert POSTROUTING -o $DEV -j THESHAPER | ||
|
||
# To speed up downloads while an upload is going on, put short ACK | ||
# packets in the interactive class: | ||
|
||
iptables -t mangle -A THESHAPER \ | ||
-p tcp \ | ||
-m tcp --tcp-flags FIN,SYN,RST,ACK ACK \ | ||
-m length --length :64 \ | ||
-j CLASSIFY --set-class 1:2 | ||
|
||
# put large (512+) icmp packets in browsing category | ||
iptables -t mangle -A THESHAPER \ | ||
-p icmp \ | ||
-m length --length 512: \ | ||
-j CLASSIFY --set-class 1:4 | ||
|
||
# ICMP (ip protocol 1) in the interactive class | ||
iptables -t mangle -A THESHAPER \ | ||
-p icmp \ | ||
-m length --length :512 \ | ||
-j CLASSIFY --set-class 1:2 | ||
|
||
setclassbyport() { | ||
port=$1 | ||
CLASS=$2 | ||
iptables -t mangle -A THESHAPER -p udp --sport $port -j CLASSIFY --set-class $CLASS | ||
iptables -t mangle -A THESHAPER -p udp --dport $port -j CLASSIFY --set-class $CLASS | ||
iptables -t mangle -A THESHAPER -p tcp --sport $port -j CLASSIFY --set-class $CLASS | ||
iptables -t mangle -A THESHAPER -p tcp --dport $port -j CLASSIFY --set-class $CLASS | ||
} | ||
|
||
for port in $INTERACTIVEPORTS; do setclassbyport $port 1:2; done | ||
for port in $VOIPPORTS; do setclassbyport $port 1:3; done | ||
for port in $BROWSINGPORTS; do setclassbyport $port 1:4; done | ||
for port in $P2PPORTS; do setclassbyport $port 1:6; done | ||
|
||
for VOIP in $VOIPIPS | ||
do | ||
iptables -t mangle -A THESHAPER --src $VOIP -j CLASSIFY --set-class 1:3 | ||
iptables -t mangle -A THESHAPER --dst $VOIP -j CLASSIFY --set-class 1:3 | ||
done | ||
|
||
# Try to control the incoming traffic as well. | ||
# Set up ingress qdisc | ||
tc qdisc add dev $DEV handle ffff: ingress | ||
|
||
# Filter everything that is coming in too fast | ||
# It's mostly HTTP downloads that keep jamming the downlink, so try to restrict | ||
# them to 6/10 of the downlink. | ||
tc filter add dev $DEV parent ffff: protocol ip prio 50 \ | ||
u32 match ip src 0.0.0.0/0 \ | ||
match ip protocol 6 0xff \ | ||
match ip sport 80 0xffff \ | ||
police rate $((6*${DOWNLINK}/10))kbit \ | ||
burst 10k drop flowid :1 | ||
|
||
tc filter add dev $DEV parent ffff: protocol ip prio 50 \ | ||
u32 match ip src 0.0.0.0/0 \ | ||
match ip protocol 6 0xff \ | ||
match ip dport 80 0xffff \ | ||
police rate $((6*${DOWNLINK}/10))kbit \ | ||
burst 10k drop flowid :1 | ||
;; | ||
*) | ||
echo "$0 [ACTION] [device]" | ||
echo "ACTION := { start [downlink] [uplink] | stop | status }" | ||
exit | ||
;; | ||
esac |