#!/bin/bash
# AstShape
# Based off of WonderShaper (HTB)
# Enhanced by Kristian Kielhofner <kris@krisk.org>
# Make sure that all of your VoIP devices set tos on RTP to 0x18
# iax.conf: tos=0x18 sip.conf: tos=0x18

# Default values
DOWNLINK=1000000
UPLINK=$DOWNLINK
QOS_ENABLE=1
QOS_DEVICE="eth0"
#VOIP priority ports
QOS_HIGH_PRIO_PORTS="5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010"
#INT priority ports
QOS_INT_PRIO_PORTS=  #"5060 5061 5062"

# configuration file
QOS_CONFIG_FILE=$1
QOS_COMMAND=$2

# qos configuration file
if [ -e "$QOS_CONFIG_FILE" ]
then

source "$QOS_CONFIG_FILE"

for DEV in $QOS_DEVICE
do
if [ "$QOS_COMMAND" = "status" ]
then
  echo $QOS_COMMAND of $DEV
	tc -s qdisc ls dev $DEV
	tc -s class ls dev $DEV
  echo
else
  # clean existing down- and uplink qdiscs, hide errors
  tc qdisc del dev $DEV root    2> /dev/null > /dev/null
  tc qdisc del dev $DEV ingress 2> /dev/null > /dev/null
  # Need to start QOS ?
  if [ "$QOS_COMMAND" = "start" ] && [ "$QOS_ENABLE" = 1 ]
  then
    ###### uplink

    #install root HTB, point default traffic to 1:3
    tc qdisc add dev $DEV root handle 1: prio

    #all get Stochastic Fairness
    tc qdisc add dev $DEV parent 1:1 handle 10: sfq
    tc qdisc add dev $DEV parent 1:2 handle 20: sfq 
    tc qdisc add dev $DEV parent 1:3 handle 30: sfq 

    #Voip TOS in 1:1
    tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 match ip tos 0x18 0xff flowid 1:1
    tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 match ip tos 0xb8 0xfc flowid 1:1
    tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 match ip tos 0x68 0xfc flowid 1:1
    tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 match ip tos 0x60 0xfc flowid 1:1

    #Ports as defined above
    for a in $QOS_HIGH_PRIO_PORTS
    do
      tc filter add dev $DEV parent 1:0 protocol ip prio 11 u32 match ip dport $a 0xffff flowid 1:1
      tc filter add dev $DEV parent 1:0 protocol ip prio 11 u32 match ip sport $a 0xffff flowid 1:1
    done

    # TOS Minimum Delay (ssh, NOT scp) in 1:2
    tc filter add dev $DEV parent 1:0 protocol ip prio 20 u32 match ip tos 0x10 0xff flowid 1:2

    #DNS in interactive class 1:2
    tc filter add dev $DEV parent 1:0 protocol ip prio 21 u32 match ip sport 53 0xffff flowid 1:2
    tc filter add dev $DEV parent 1:0 protocol ip prio 22 u32 match ip dport 53 0xffff flowid 1:2

    #Ports as defined above
    for a in $QOS_INT_PRIO_PORTS
    do
      tc filter add dev $DEV parent 1:0 protocol ip prio 24 u32 match ip dport $a 0xffff flowid 1:3
      tc filter add dev $DEV parent 1:0 protocol ip prio 24 u32 match ip sport $a 0xffff flowid 1:3
    done

    #ICMP (ip protocol 1) in the interactive class 1:2
    tc filter add dev $DEV parent 1: protocol ip prio 25 u32 match ip protocol 1 0xff flowid 1:2

    #rest is 'non-interactive' ie 'bulk' and ends up in 1:3
    tc filter add dev $DEV parent 1: protocol ip prio 30 u32 match ip dst 0.0.0.0/0 flowid 1:3

  fi
fi

done

fi

exit


