#! /bin/sh
IP="/sbin/ip"
TC="/sbin/tc"
IPT="/sbin/iptables"
##What interface to run on?
IFACE_NET="eth0"
## Run this script with "status" as an argument to display stats
if [ "$1" = "status" ] ; then ${TC} -s qdisc ls dev ${IFACE_NET} ; exit 0 ; fi

## These are numbers in kilobytes per second
UPSTREAM_TOTAL="28"
##Ultrahi is udp packets and tcp ack packets
##lo is the default class, all non classified port traffic will go into it
## These should add up to _TOTAL
UPSTREAM_ULTRAHI="12"
UPSTREAM_HI="9"
UPSTREAM_MED="5"
UPSTREAM_MEDLO="1"
UPSTREAM_LO="1"



## Interface Maximum Transmission Unit
MTU_NET="1500"

PORTS_HI="25 80 53 110"
PORTS_MED="20 21 22 23 15111 15112 15113"
PORTS_MEDLO="1214 2234 4242 4661 4662 4672 5534 33333 33334 33340 33341 44000 44001"

###############################################################################

## Delete old rules
${TC} qdisc del dev ${IFACE_NET} root

## Set MTU
${IP} link set dev ${IFACE_NET} mtu ${MTU_NET}

## Set queue size
${IP} link set dev ${IFACE_NET} qlen 2

## Create root queue discipline
${TC} qdisc add dev ${IFACE_NET} root handle 1:0 htb default 14

## Create root class
${TC} class add dev ${IFACE_NET} parent 1:0 classid 1:1 htb rate ${UPSTREAM_TOTAL}kbps

## Create leaf classes where packets will actually be classified
${TC} class add dev ${IFACE_NET} parent 1:1 classid 1:10 htb prio 0 rate ${UPSTREAM_ULTRAHI}kbps ceil ${UPSTREAM_TOTAL}kbps
${TC} class add dev ${IFACE_NET} parent 1:1 classid 1:11 htb prio 1 rate ${UPSTREAM_HI}kbps ceil ${UPSTREAM_TOTAL}kbps
${TC} class add dev ${IFACE_NET} parent 1:1 classid 1:12 htb prio 2 rate ${UPSTREAM_MED}kbps ceil ${UPSTREAM_TOTAL}kbps
${TC} class add dev ${IFACE_NET} parent 1:1 classid 1:13 htb prio 3 rate ${UPSTREAM_MEDLO}kbps ceil ${UPSTREAM_TOTAL}kbps
${TC} class add dev ${IFACE_NET} parent 1:1 classid 1:14 htb prio 4 rate ${UPSTREAM_LO}kbps ceil ${UPSTREAM_TOTAL}kbps

## Add SFQ for beneath these classes
${TC} qdisc add dev ${IFACE_NET} parent 1:10 handle 10: sfq perturb 10
${TC} qdisc add dev ${IFACE_NET} parent 1:11 handle 11: sfq perturb 10
${TC} qdisc add dev ${IFACE_NET} parent 1:12 handle 12: sfq perturb 10
${TC} qdisc add dev ${IFACE_NET} parent 1:13 handle 13: sfq perturb 10 
${TC} qdisc add dev ${IFACE_NET} parent 1:14 handle 14: sfq perturb 10 

# ICMP (ip protocol 1) in the interactive class 1:11 so we
# can do measurements & impress our friends:
${TC} filter add dev ${IFACE_NET} parent 1:0 protocol ip prio 0 u32 \
	match ip protocol 1 0xff \
	flowid 1:10
 
# prioritize small packets (<64 bytes)
${TC} filter add dev ${IFACE_NET} parent 1:0 protocol ip prio 0 u32 \
	match ip protocol 6 0xff \
	match u8 0x05 0x0f at 0 \
	match u16 0x0000 0xffc0 at 2 \
	match u8 0x10 0xff at 33 \
	flowid 1:10

#prioritize udp packets. Delete if you don't want to prioritize these
${TC} filter add dev ${IFACE_NET} parent 1:0 protocol ip prio 0 u32 \
	match ip protocol 17 0xff \
	flowid 1:10

## Add the filters which direct traffic to the right classes
## High-priority traffic
for PORT in ${PORTS_HI}; do
        ${TC} filter add dev ${IFACE_NET} protocol ip parent 1:0 prio 0 u32 match ip dport ${PORT} 0xffff flowid 1:11
        ${TC} filter add dev ${IFACE_NET} protocol ip parent 1:0 prio 0 u32 match ip sport ${PORT} 0xffff flowid 1:11
done

## Normal traffic
for PORT in ${PORTS_MED}; do
        ${TC} filter add dev ${IFACE_NET} protocol ip parent 1:0 prio 0 u32 match ip dport ${PORT} 0xffff flowid 1:12
        ${TC} filter add dev ${IFACE_NET} protocol ip parent 1:0 prio 0 u32 match ip sport ${PORT} 0xffff flowid 1:12
done

## Normal Lo traffic
for PORT in ${PORTS_MEDLO}; do
        ${TC} filter add dev ${IFACE_NET} protocol ip parent 1:0 prio 0 u32 match ip dport ${PORT} 0xffff flowid 1:13
        ${TC} filter add dev ${IFACE_NET} protocol ip parent 1:0 prio 0 u32 match ip sport ${PORT} 0xffff flowid 1:13
done 
