#!/bin/sh
# Cero3 Simple Shaper
# A 1 bin tc_codel and ipv6 enabled shaping script for
# ethernet gateways. This is nearly the simplest possible

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
#       Copyright (C) 2012-4 Michael D. Taht, Toke Høiland-Jørgensen, Sebastian Moeller

. /usr/lib/sqm/functions.sh
sqm_logger "Starting simplest.qos"

egress() {

LQ="quantum `get_mtu $IFACE ${UPLINK}`"

$TC qdisc del dev $IFACE root 2>/dev/null
$TC qdisc add dev $IFACE root handle 1: `get_stab_string` htb default 10
$TC class add dev $IFACE parent 1: classid 1:1 htb $LQ rate ${UPLINK}kbit ceil ${UPLINK}kbit `get_htb_adsll_string`
$TC class add dev $IFACE parent 1:1 classid 1:10 htb $LQ rate ${UPLINK}kbit ceil ${UPLINK}kbit prio 0 `get_htb_adsll_string`
$TC qdisc add dev $IFACE parent 1:10 handle 110: $QDISC `get_limit ${ELIMIT}` `get_target "${ETARGET}" ${UPLINK}` `get_ecn ${EECN}` `get_flows ${UPLINK}` ${EQDISC_OPTS}

}


ingress() {
sqm_logger "ingress"
$TC qdisc del dev $IFACE handle ffff: ingress 2>/dev/null
$TC qdisc add dev $IFACE handle ffff: ingress

LQ="quantum `get_mtu $IFACE ${DOWNLINK}`"
 
$TC qdisc del dev $DEV root 2>/dev/null
$TC qdisc add dev $DEV root handle 1: `get_stab_string` htb default 10
$TC class add dev $DEV parent 1: classid 1:1 htb $LQ rate ${DOWNLINK}kbit ceil ${DOWNLINK}kbit `get_htb_adsll_string`
$TC class add dev $DEV parent 1:1 classid 1:10 htb $LQ rate ${DOWNLINK}kbit ceil ${DOWNLINK}kbit prio 0 `get_htb_adsll_string`

# FIXME: I'd prefer to use a pre-nat filter but we need to detect if nat is on this interface
# AND we need to permute by a random number which we can't do from userspace filters

# Most high rate flows are REALLY close. This stomps on those harder, but hurts on high rate long distance
#$TC qdisc add dev $DEV parent 1:10 handle 110: $QDISC limit $LIMIT $ECN interval 20ms target 3ms `get_flows ${DOWNLINK}`
$TC qdisc add dev $DEV parent 1:10 handle 110: $QDISC `get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_flows ${DOWNLINK}` ${IQDISC_OPTS}

ifconfig $DEV up

# redirect all IP packets arriving in $IFACE to ifb0 

$TC filter add dev $IFACE parent ffff: protocol all prio 10 u32 \
  match u32 0 0 flowid 1:1 action mirred egress redirect dev $DEV

}

do_modules

if [ "$UPLINK" -ne 0 ];
then
	egress
	sqm_logger "egress shaping activated"
else
	sqm_logger "egress shaping deactivated"
	tc qdisc del dev $IFACE root 2> /dev/null
fi
if [ "$DOWNLINK" -ne 0 ];
then
	ingress
	sqm_logger "ingress shaping activated"
else
	sqm_logger "ingress shaping deactivated"
	tc qdisc del dev $DEV root 2> /dev/null
	tc qdisc del dev $IFACE ingress 2> /dev/null
fi


# References:
# This alternate shaper attempts to go for 1/u performance in a clever way
# http://git.coverfire.com/?p=linux-qos-scripts.git;a=blob;f=src-3tos.sh;hb=HEAD

# Comments
# This does the right thing with ipv6 traffic.
# Flaws
# Many!
