#!/bin/bash
# eth1 is the DSL line 

IPT='/sbin/iptables'
TC='/sbin/tc'
IP='/sbin/ip'

DEV=eth1
RATEUP=335
RATEUP1=315

# load some modules
/sbin/modprobe ipt_length
/sbin/modprobe ipt_limit 

echo "Reseting traffic shaper to known state"
$TC qdisc del dev $DEV root    2> /dev/null > /dev/null
$TC qdisc del dev imq0 root 2> /dev/null > /dev/null
$IPT -t mangle -D POSTROUTING -o $DEV -j MYSHAPER-OUT 2> /dev/null > /dev/null
$IPT -t mangle -F MYSHAPER-OUT 2> /dev/null > /dev/null
$IPT -t mangle -X MYSHAPER-OUT 2> /dev/null > /dev/null
$IPT -t mangle -D PREROUTING -i $DEV -j MYSHAPER-IN 2> /dev/null > /dev/null
$IP link set imq0 down 2> /dev/null > /dev/null

# add HTB root qdisc
$TC qdisc add dev $DEV root handle 1: htb default 23

echo "Limiting upload rates"
# set queue size to whatever you want
$IP link set dev $DEV qlen 30

# lower the MTU to decrease latency
$IP link set dev $DEV mtu 576

# add main rate limit classes
$TC class add dev $DEV parent 1: classid 1:1 htb rate ${RATEUP}kbit burst 6k

# add leaf classes - We grant each class at LEAST it's "fair share" of 
# bandwidth. this way no class will ever be starved by another class.  Each
# class is also permitted to consume all of the available bandwidth
# if no other classes are in use.

$TC class add dev $DEV parent 1:1 classid 1:20 htb rate ${RATEUP}kbit burst 6k prio 0
$TC class add dev $DEV parent 1:1 classid 1:21 htb rate ${RATEUP}kbit burst 6k prio 1
$TC class add dev $DEV parent 1:1 classid 1:22 htb rate ${RATEUP1}kbit burst 6k prio 2
$TC class add dev $DEV parent 1:1 classid 1:23 htb rate ${RATEUP1}kbit burst 6k prio 3

# attach qdisc to leaf classes - here we at SFQ to each priority class.  SFQ 
# insures that within each class connections will be treated (almost) fairly.  

$TC qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10
$TC qdisc add dev $DEV parent 1:21 handle 21: sfq perturb 10
$TC qdisc add dev $DEV parent 1:22 handle 22: sfq perturb 10
$TC qdisc add dev $DEV parent 1:23 handle 23: sfq perturb 10

# filter traffic into classes by fwmark - here we direct traffic into priority 
# class according to the fwmark set on the packet (we set fwmark with $IPT 
# later).  Note that above we've set the default priority class to 1:26 so 
# unmarked packets (or packets marked with unfamiliar IDs) will be defaulted 
# to the lowest priority class.

$TC filter add dev $DEV parent 1:0 prio 0 protocol ip handle 20 fw flowid 1:20
$TC filter add dev $DEV parent 1:0 prio 0 protocol ip handle 21 fw flowid 1:21
$TC filter add dev $DEV parent 1:0 prio 0 protocol ip handle 22 fw flowid 1:22
$TC filter add dev $DEV parent 1:0 prio 0 protocol ip handle 23 fw flowid 1:23

# add MYSHAPER-OUT chain to the mangle table in $IPT - this sets up the table 
# we'll use to filter and mark packets.
$IPT -t mangle -N MYSHAPER-OUT
$IPT -t mangle -I POSTROUTING -o $DEV -j MYSHAPER-OUT

# add fwmark entries to classify different types of traffic - Set fwmark from 
# 20-26 according to desired class. 20 is highest prio.

# Default for low port traffic 
$IPT -t mangle -A MYSHAPER-OUT -p tcp --sport 0:1024 -j MARK --set-mark 22 
$IPT -t mangle -A MYSHAPER-OUT -p tcp --dport 0:1024 -j MARK --set-mark 22 

# ftp-data port, low prio
$IPT -t mangle -A MYSHAPER-OUT -p tcp --dport 20 -j MARK --set-mark 23

# aim
$IPT -t mangle -A MYSHAPER-OUT -p tcp --dport 5190 -j MARK --set-mark 22

# ICMP - low priority (who cares?)
$IPT -t mangle -A MYSHAPER-OUT -p icmp -j MARK --set-mark 20

# DNS name resolution (small packets)
$IPT -t mangle -A MYSHAPER-OUT -p udp -j MARK --set-mark 21

# ssh
$IPT -t mangle -A MYSHAPER-OUT -p tcp --dport ssh -j MARK --set-mark 20
$IPT -t mangle -A MYSHAPER-OUT -p tcp --sport ssh -j MARK --set-mark 20

# irc/ircd
$IPT -t mangle -A MYSHAPER-OUT -p tcp --dport 6667 -j MARK --set-mark 21
$IPT -t mangle -A MYSHAPER-OUT -p tcp --sport 6667 -j MARK --set-mark 21

# mark all traffic to/from my.favouritehost.com as high priority
$IPT -t mangle -A MYSHAPER-OUT -p tcp -s 192.168.1.1 -j MARK --set-mark 21
$IPT -t mangle -A MYSHAPER-OUT -p tcp -d 192.168.1.1 -j MARK --set-mark 21


# telnet
$IPT -t mangle -A MYSHAPER-OUT -p tcp --dport telnet -j MARK --set-mark 21
$IPT -t mangle -A MYSHAPER-OUT -p tcp --sport telnet -j MARK --set-mark 21

# apache
$IPT -t mangle -A MYSHAPER-OUT -p tcp --sport http -j MARK --set-mark 23

# small packets (probably just ACKs)
$IPT -t mangle -A MYSHAPER-OUT -p tcp -m length --length :64 -j MARK --set-mark 20

# redundant- mark any unmarked packets as 23 (low prio)
$IPT -t mangle -A MYSHAPER-OUT -m mark --mark 0 -j MARK --set-mark 23

# Done with outbound shaping
#
####################################################

echo "Outbound shaping added to $DEV.  Rate: ${RATEUP}Kbit/sec."

