Skip to content

Instantly share code, notes, and snippets.

@bartvandendriessche
Created August 28, 2010 17:25
Show Gist options
  • Select an option

  • Save bartvandendriessche/555363 to your computer and use it in GitHub Desktop.

Select an option

Save bartvandendriessche/555363 to your computer and use it in GitHub Desktop.
#!/bin/ash
# Modified to run under DD-WRT
# http://www.morph3ous.net/2009/11/20/beta-hfsc-traffic-shaping-for-qos-on-dd-wrt/
# Go to Administration and then commands
# Paste script in and click on the save firewall button
# Reboot router and test
# 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 the uplink as 85 or 90 percent of your actual upload speed
# Uplink and downlink speeds
# removed throttling downlink
UPLINK=300
###### From original script, but code has been disabled further below
# IP addresses of the VoIP phones,
# if none, set VOIPIPS=""
VOIPIPS=""
######
# Interactive class: SSH Terminal, DNS, RDP
INTERACTIVEPORTS="22 23 53 3389 27960:27980"
# VoIP telephony
#VOIPPORTS="5060:5100 10000:11000 5000:5059 8000:8016 5004 1720 1731"
VOIPPORTS=""
# WWW, jabber and IRC
BROWSINGPORTS="80 443 3000 8080"
# The lowest priority traffic: IMAP, SMTP, FTP, IMAP, IMAP/S, high port numbers likely to be P2P
P2PPORTS="110 25 21 143 993 1024:65535"
# Device that connects you to the Internet
DEV=$(nvram get wan_ifname)
# clean up in case re-running
# 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
# start setting up QOS
# Traffic classes:
# 1:2 Interactive (SSH, DNS, ACK, Quake)
# 1:3 Low latency (VoIP) < - currently being used for Netflix movie streaming from Roku box
# 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
tc class add dev $DEV parent 1:1 classid 1:2 hfsc sc umax 1500b dmax 30ms rate $((5*$UPLINK/10))kbit ul rate ${UPLINK}kbit
# Netflix
tc class add dev $DEV parent 1:1 classid 1:3 hfsc sc umax 1500b dmax 75ms rate $((2*$UPLINK/10))kbit ul rate ${UPLINK}kbit
# Browsing
tc class add dev $DEV parent 1:1 classid 1:4 hfsc sc rate $((1*$UPLINK/10))kbit ul rate ${UPLINK}kbit
# Default traffic
tc class add dev $DEV parent 1:1 classid 1:5 hfsc sc rate $((1*$UPLINK/20))kbit ul rate ${UPLINK}kbit
# Low priority/Bulk
tc class add dev $DEV parent 1:1 classid 1:6 hfsc sc rate 500bit 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
# had to change all iptables rules below to use mark instead of classify. tc filters then pick these up and move to the proper queue
# in the future this should all be done with tc filters as this is somewhat of a hack and there is presumably at least slightly more overhead
# put packets marked by iptables in the right queues using tc filters
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 2 fw flowid 1:2
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 3 fw flowid 1:3
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 4 fw flowid 1:4
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 5 fw flowid 1:5
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 6 fw flowid 1:6
## Note that iptables rules are being appended to the end of the chain. It appears that in the mangle
## table when using mark, all rules are processed
## put more specific rules lower down in the script otherwise more general rules below them may
## re-mark them and cause unexpected behavior
### UNLESS ##
## You add another rule with -j RETURN
## I'm doing this with some rules because I want them to be processed first. It also
## helps keep the packet statistics cleaner when issuing the iptables -t mangle -L -v command (otherwise some traffic is double-counted)
# 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 MARK --set-mark 2
iptables -t mangle -A THESHAPER -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK ACK -m length --length :64 -j RETURN
# put large (512+) icmp packets in browsing category
iptables -t mangle -A THESHAPER -p icmp -m length --length 512: -j MARK --set-mark 4
iptables -t mangle -A THESHAPER -p icmp -m length --length 512: -j RETURN
# ICMP (ip protocol 1) in the interactive class
iptables -t mangle -A THESHAPER -p icmp -m length --length :512 -j MARK --set-mark 2
iptables -t mangle -A THESHAPER -p icmp -m length --length :512 -j RETURN
setclassbyport() {
port=$1
CLASS=$2
iptables -t mangle -A THESHAPER -p udp --sport $port -j MARK --set-mark $CLASS
iptables -t mangle -A THESHAPER -p udp --dport $port -j MARK --set-mark $CLASS
iptables -t mangle -A THESHAPER -p tcp --sport $port -j MARK --set-mark $CLASS
iptables -t mangle -A THESHAPER -p tcp --dport $port -j MARK --set-mark $CLASS
}
for port in $INTERACTIVEPORTS; do setclassbyport $port 2; done
for port in $VOIPPORTS; do setclassbyport $port 3; done
for port in $BROWSINGPORTS; do setclassbyport $port 4; done
for port in $P2PPORTS; do setclassbyport $port 6; done
for VOIP in $VOIPIPS
do
iptables -t mangle -A THESHAPER --src $VOIP -j MARK --set-mark 3
iptables -t mangle -A THESHAPER --dst $VOIP -j MARK --set-mark 3
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment