#!/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