Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
automaciej committed Nov 22, 2011
0 parents commit 1a1631d
Show file tree
Hide file tree
Showing 2 changed files with 218 additions and 0 deletions.
1 change: 1 addition & 0 deletions README
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
HFSC traffic shaping helper script
217 changes: 217 additions & 0 deletions hfsc
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

0 comments on commit 1a1631d

Please sign in to comment.