hfsc ตัวอย่าง
#!/bin/bash
# encoding: UTF-8
#
# HFSC helper script
# (c) 2006-2011 Maciej Bliziński
#
http://automatthias.wordpress.com/#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#
# References:
# - Original shell script:
#
http://www.voip-info.org/wiki/view/QoS+Linux+with+HFSC# - Kernel configuration (probably not necessary on modern distros)
#
http://www.nslu2-linux.org/wiki/HowTo/EnableTrafficShaping# - Hierarchical Packet Schedulers presentation
#
http://www.cs.cmu.edu/~hzhang/HFSC/main.html# - HFSC Scheduling with Linux
#
http://linux-ip.net/articles/hfsc.en/#
# When specifying parameters of your xDSL, provide 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 8080 443"
#VOIPPORTS=""
# WWW, jabber and IRC
BROWSINGPORTS="80"
# 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