#!/bin/sh
#
# Setup QOS stuff for a single host on the LAN

# $1  - hostname
# $2  - host ip
# $3  - class base number
# $4  - priority class
# $5  - medium class
# $6  - bulk class
# $7  - host upload rate
# $8  - host upload ceil
# $9  - host download rate
# $10 - host download ceil
# $11 - priority traffic upload rate
# $12 - priority traffic upload ceil
# $13 - priority traffic download rate
# $14 - priority traffic download ceil
# $15 - bulk traffic upload rate
# $16 - bulk traffic upload ceil
# $17 - bulk traffic download rate
# $18 - bulk traffic download ceil

if [ -z "$18" ]; then
    echo "$0 should not be called without parameters"
    exit 1
fi

HOSTNAME=$1
HOST_IP=$2
CLASS_BASE=$3
CLASS_PRIO=$4
CLASS_MEDIUM=$5
CLASS_BULK=$6
HOST_UP_RATE=$7
HOST_UP_CEIL=$8
HOST_DOWN_RATE=$9
HOST_DOWN_CEIL=$10
PRIO_UP_RATE=$11
PRIO_UP_CEIL=$12
PRIO_DOWN_RATE=$13
PRIO_DOWN_CEIL=$14
BULK_UP_RATE=$15
BULK_UP_CEIL=$16
BULK_DOWN_RATE=$17
BULK_DOWN_CEIL=$18

# ---------------------------------------------------------------
echo " - $HOSTNAME base classes"
if [ $HOSTNAME != lanlan ]; then
    echo " - (class 1:$CLASS_BASE) $HOSTNAME -> $EX_IF : rate=$HOST_UP_RATE, ceil=$HOST_UP_CEIL"
    tc class add dev $EX_IF parent 1:1 classid 1:$CLASS_BASE htb \
        rate $HOST_UP_RATE ceil $HOST_UP_CEIL
fi
echo " - (class 2:$CLASS_BASE) $HOSTNAME -> $LAN_IF : rate=$HOST_DOWN_RATE, ceil=$HOST_DOWN_CEIL"
tc class add dev $LAN_IF parent 2:1 classid 2:$CLASS_BASE htb \
    rate $HOST_DOWN_RATE ceil $HOST_DOWN_CEIL

# ---------------------------------------------------------------
echo " - setting up priority traffic classes and filters (1:$CLASS_PRIO & 2:$CLASS_PRIO)"

if [ $HOSTNAME != lanlan ]; then
    echo " - $HOSTNAME -> $EX_IF : rate=$PRIO_UP_RATE, ceil=$PRIO_UP_CEIL, fwmark=$CLASS_PRIO"
    tc class add dev $EX_IF parent 1:$CLASS_BASE classid 1:$CLASS_PRIO htb \
        rate $PRIO_UP_RATE ceil $PRIO_UP_CEIL prio 1
    tc filter add dev $EX_IF parent 1:0 protocol ip prio 1 \
        handle $CLASS_PRIO fw classid 1:$CLASS_PRIO
    echo " - setting up pfifo on class 1:$CLASS_PRIO"

    # Unresolved: use pfifo or sfq for priority queue?
    #tc qdisc add dev $EX_IF parent 1:$CLASS_PRIO pfifo limit 10
    tc qdisc add dev $EX_IF parent 1:$CLASS_PRIO sfq perturb 1
fi
    
echo " - $HOSTNAME -> $LAN_IF : rate=$PRIO_DOWN_RATE, ceil=$PRIO_DOWN_CEIL, fwmark=$CLASS_PRIO"
tc class add dev $LAN_IF parent 2:$CLASS_BASE classid 2:$CLASS_PRIO htb \
    rate $PRIO_DOWN_RATE ceil $PRIO_DOWN_CEIL prio 1
tc filter add dev $LAN_IF parent 2:0 protocol ip prio 1 \
    handle $CLASS_PRIO fw classid 2:$CLASS_PRIO
echo " - setting up pfifo on class 2:$CLASS_PRIO"

#tc qdisc add dev $LAN_IF parent 2:$CLASS_PRIO pfifo limit 10
tc qdisc add dev $LAN_IF parent 2:$CLASS_PRIO sfq perturb 1

# ---------------------------------------------------------------
echo " - setting up medium priority traffic classes and filters (1:$CLASS_MEDIUM & 2:$CLASS_MEDIUM)"

# Bandwidth is the same as priority class just with less priority
if [ $HOSTNAME != lanlan ]; then
    echo " - $HOSTNAME -> $EX_IF : rate=$PRIO_UP_RATE, ceil=$PRIO_UP_CEIL, fwmark=$CLASS_MEDIUM"
    tc class add dev $EX_IF parent 1:$CLASS_BASE classid 1:$CLASS_MEDIUM htb \
        rate $PRIO_UP_RATE ceil $PRIO_UP_CEIL prio 2
    tc filter add dev $EX_IF parent 1:0 protocol ip prio 1 \
        handle $CLASS_MEDIUM fw classid 1:$CLASS_MEDIUM
    echo " - setting up fair queuing on class 1:$CLASS_MEDIUM"
    tc qdisc add dev $EX_IF parent 1:$CLASS_MEDIUM sfq perturb 10
fi
    
echo " - $HOSTNAME -> $LAN_IF : rate=$PRIO_DOWN_RATE, ceil=$PRIO_DOWN_CEIL, fwmark=$CLASS_MEDIUM"
tc class add dev $LAN_IF parent 2:$CLASS_BASE classid 2:$CLASS_MEDIUM htb \
    rate $PRIO_DOWN_RATE ceil $PRIO_DOWN_CEIL prio 2
tc filter add dev $LAN_IF parent 2:0 protocol ip prio 1 \
    handle $CLASS_MEDIUM fw classid 2:$CLASS_MEDIUM
echo " - setting up fair queuing on class 2:$CLASS_MEDIUM"
tc qdisc add dev $LAN_IF parent 2:$CLASS_MEDIUM sfq perturb 10

# ---------------------------------------------------------------
echo " - setting up bulk traffic classes and filters (1:$CLASS_BULK & 2:$CLASS_BULK)"

if [ $HOSTNAME != lanlan ]; then
    echo " - $HOSTNAME -> $EX_IF : rate=$BULK_UP_RATE, ceil=$BULK_UP_CEIL, fwmark=$CLASS_BULK"
    tc class add dev $EX_IF parent 1:$CLASS_BASE classid 1:$CLASS_BULK htb \
        rate $BULK_UP_RATE ceil $BULK_UP_CEIL prio 6
    tc filter add dev $EX_IF parent 1:0 protocol ip prio 1 \
        handle $CLASS_BULK fw classid 1:$CLASS_BULK
    echo " - setting up fair queuing on class 1:$CLASS_BULK"
    tc qdisc add dev $EX_IF parent 1:$CLASS_BULK sfq perturb 10
fi
    
echo " - $HOSTNAME -> $LAN_IF : rate=$BULK_DOWN_RATE, ceil=$BULK_DOWN_CEIL, fwmark=$CLASS_BULK"
tc class add dev $LAN_IF parent 2:$CLASS_BASE classid 2:$CLASS_BULK htb \
    rate $BULK_DOWN_RATE ceil $BULK_DOWN_CEIL prio 6
tc filter add dev $LAN_IF parent 2:0 protocol ip prio 1 \
    handle $CLASS_BULK fw classid 2:$CLASS_BULK
echo " - setting up fair queuing on class 2:$CLASS_BULK"
tc qdisc add dev $LAN_IF parent 2:$CLASS_BULK sfq perturb 10

# ---------------------------------------------------------------
# If HOSTNAME is "lanlan", this is a special case of LAN->LAN traffic
if [ $HOSTNAME = lanlan ]; then
    echo " - generating LAN->LAN traffic iptables classifiers"
    # Need to use incoming so that lan->lan traffic is the first rule for
    # postrouting in the mangle table
    # Also put it in outgoing so that the iptables counters will be correct
    ./rc.qos.iptables $HOSTNAME $HOST_IP $HOST_IP $CLASS_PRIO $CLASS_MEDIUM $CLASS_BULK incoming
    ./rc.qos.iptables $HOSTNAME $HOST_IP $HOST_IP $CLASS_PRIO $CLASS_MEDIUM $CLASS_BULK outgoing
else
    echo " - generating incoming traffic iptables classifiers"
    ./rc.qos.iptables $HOSTNAME 0.0.0.0/0 $HOST_IP $CLASS_PRIO $CLASS_MEDIUM $CLASS_BULK incoming

    echo " - generating outgoing traffic iptables classifiers"
    ./rc.qos.iptables $HOSTNAME $HOST_IP 0.0.0.0/0 $CLASS_PRIO $CLASS_MEDIUM $CLASS_BULK outgoing
fi
