#!/bin/sh
# wondershaper amc-1.0.2 (2014-Feb-01-Sat)
#
# Derived by Adam M. Costello from
# wondershaper 1.1 as modified by
# Debian ; therefore it is licensed under the
# GPL .
# This script uses the HTB qdisc, which gets fatally confused by TCP
# Segmentation Offload (TSO, also known as TCP Large Send). One sign
# that this is happening is that 'tc -s class show dev '
# reports a nonzero number of 'giants' (packets larger than the MTU).
#
# If your ethernet interface supports TSO, you need to disable it via
# 'ethtool -K tso off', probably at the same time/place you
# run this script.
if [ $# -eq 0 -o $# -gt 5 ]; then
myname=`basename "$0"`
cat << EOF
for status: $myname
to clear: $myname clear
to shape: $myname [ ]
may be '-' to disable downlink policing.
and are percentages of the uplink guaranteed for medium
and low priority traffic, defaulting to 30 and 20, respectively.
100% - - is guaranteed for high priority traffic.
Low priority address prefixes and ports can be specified via environment
variables, see the comments in $0.
Remember to disable TSO, see the comments in $0.
EOF
exit
fi
if [ $# -eq 1 ]; then
tc -s qdisc ls dev $1
tc -s class ls dev $1
exit
fi
if [ $# -eq 2 ]; then
tc qdisc del dev $2 root 2> /dev/null > /dev/null
tc qdisc del dev $2 ingress 2> /dev/null > /dev/null
echo Wondershaper queues have been cleared.
exit
fi
# Set the following values to somewhat less than your actual download
# and uplink speed. In kilobits. Also set the device that is to be shaped.
DOWNLINK=$2
UPLINK=$3
DEV=$1
# Percentages of the uplink guaranteed to the medium and low priority
# classes. The remainder (100 minus those) will be implicitly
# guaranteed to the high priority class.
MED_PRIO_PERCENT=${4-30}
LOW_PRIO_PERCENT=${5-20}
# You can optionally specify low priority uplink traffic according to
# source/destination IP address prefixes and/or port numbers, by setting
# environment variables. For example:
# LOW_PRIO_SRC_ADDR=1.2.3.4/32
# LOW_PRIO_DST_ADDR='5.6.7.16/28 8.9.40.0/22'
# LOW_PRIO_SRC_PORT='50000 50001 50002'
# LOW_PRIO_DST_PORT=60000
read junk1 junk2 junk3 LOCALNET junk << EOF
`ip -o -f inet addr show dev $DEV`
EOF
#########################################################
# 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
###### uplink
# install root HTB, point default traffic to 1:20:
tc qdisc add dev $DEV root handle 1: htb default 20
# shape everything non-local at $UPLINK speed - this prevents huge
# queues in your DSL/cable modem which destroy latency:
# main root class 1:1 (ceil, quantum, and prio are not applicable
# because a root class does not borrow):
tc class add dev $DEV parent 1: classid 1:1 htb rate ${UPLINK}kbit
# For the child classes we use the minimum advisable quantum (which
# sfq seems to think is 1514, though I don't know what those extra 14
# bytes are for) and the default (minimum) burst and cburst, in order
# to minimize the queue depths. They all get a ceil of $UPLINK so that
# bandwidth doesn't go to waste if only one class has stuff to send.
# high prio class 1:10 doesn't need any guaranteed bandwidth because it
# has the highest priority (it is effectively guaranteed the portion of
# the bandwidth not guaranteed to other classes).
tc class add dev $DEV parent 1:1 classid 1:10 htb prio 1 quantum 1514 \
ceil ${UPLINK}kbit rate 1bps
# (A rate of zero is not allowed for some reason.)
# default class 1:20 gets a lower priority, and some guaranteed
# bandwidth so that it won't starve:
tc class add dev $DEV parent 1:1 classid 1:20 htb prio 2 quantum 1514 \
ceil ${UPLINK}kbit rate $(($MED_PRIO_PERCENT*$UPLINK/100))kbit
# 'traffic we hate' class 1:30 gets an even lower priority, and less
# guaranteed bandwidth:
tc class add dev $DEV parent 1:1 classid 1:30 htb prio 3 quantum 1514 \
ceil ${UPLINK}kbit rate $(($LOW_PRIO_PERCENT*$UPLINK/100))kbit
# root class 1:2 for traffic within the local network. It does not need
# to be shaped, so give it an effectively infinite rate limit:
tc class add dev $DEV parent 1: classid 1:2 htb rate 34gbit
# (34gbit is about the highest rate tc will accept, because it
# represents rates internally as 32-bit unsigned bytes per second, as of
# version iproute2-ss131122.)
# all leaves under the shaped root get Stochastic Fairness:
tc qdisc add dev $DEV parent 1:10 handle 10: sfq perturb 5
tc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 5
tc qdisc add dev $DEV parent 1:30 handle 30: sfq perturb 5
# start filters
# Don't shape anything going to the local network:
tc filter add dev $DEV parent 1: protocol ip prio 9 u32 \
match ip dst $LOCALNET flowid 1:2
# TOS Minimum Delay (ssh, NOT scp) in 1:10:
tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \
match ip tos 0x10 0xff flowid 1:10
# ICMP (ip protocol 1) in the interactive class 1:10 so we
# can do measurements & impress our friends:
tc filter add dev $DEV parent 1:0 protocol ip prio 11 u32 \
match ip protocol 1 0xff flowid 1:10
# pablo.iranzo@uv.es provided a patch for the MLDonkey system
# The MLDonkey uses small UDP packets for source propogation
# which floods the wondershaper out.
tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \
match ip protocol 17 0xff \
match ip sport 4666 0xffff \
flowid 1:30
# prioritize small packets (<64 bytes)
tc filter add dev $DEV parent 1: protocol ip prio 12 u32 \
match ip protocol 6 0xff \
match u8 0x05 0x0f at 0 \
match u16 0x0000 0xffc0 at 2 \
flowid 1:10
# some traffic however suffers a worse fate
for a in $LOW_PRIO_DST_PORT
do
tc filter add dev $DEV parent 1: protocol ip prio 14 u32 \
match ip dport $a 0xffff flowid 1:30
done
for a in $LOW_PRIO_SRC_PORT
do
tc filter add dev $DEV parent 1: protocol ip prio 15 u32 \
match ip sport $a 0xffff flowid 1:30
done
for a in $LOW_PRIO_SRC_ADDR
do
tc filter add dev $DEV parent 1: protocol ip prio 16 u32 \
match ip src $a flowid 1:30
done
for a in $LOW_PRIO_DST_ADDR
do
tc filter add dev $DEV parent 1: protocol ip prio 17 u32 \
match ip dst $a flowid 1:30
done
# rest is 'non-interactive' and ends up in 1:20 by default
# Skip the downlink stuff if DOWNLINK is '-'.
[ "$DOWNLINK" != - ] || exit 0
########## downlink #############
# slow downloads down to somewhat less than the real speed to prevent
# queuing at our ISP. Tune to see how high you can set it.
# ISPs tend to have *huge* queues to make sure big downloads are fast
#
# attach ingress policer:
tc qdisc add dev $DEV handle ffff: ingress
# Don't police anything coming from the local network:
tc filter add dev $DEV parent ffff: protocol ip prio 40 u32 match ip src \
$LOCALNET police mtu 1 pass flowid :2
# filter *everything* to it (0.0.0.0/0), drop everything that's
# coming in too fast:
tc filter add dev $DEV parent ffff: protocol ip prio 50 u32 match ip src \
0.0.0.0/0 police rate ${DOWNLINK}kbit burst 10k drop flowid :1