summaryrefslogtreecommitdiff
path: root/localqos
diff options
context:
space:
mode:
Diffstat (limited to 'localqos')
-rwxr-xr-xlocalqos268
1 files changed, 268 insertions, 0 deletions
diff --git a/localqos b/localqos
new file mode 100755
index 0000000..b969bd1
--- /dev/null
+++ b/localqos
@@ -0,0 +1,268 @@
+#!/bin/bash
+#
+# Shaper to share two connection more or less equally among a number of users.
+# By Rune Kock, rune.kock@gmail.com
+#
+# Inspired by Jim diGriz's QoS Scheduler (http://www.digriz.org.uk/jdg-qos-script/)
+# and by the WRR example.
+#
+# Dependencies
+# ------------
+# 1) HTB3, RED (has been in the kernel for years)
+# 3) iptables utility (www.netfilter.org)
+# 4) tc utility (developer.osdl.org/dev/iproute2)
+# 6) WRR patch (www.zz9.dk/wrr) and tc patch
+# 7) IMQ patch (www.linuximq.net) and iptables patch NOTE: in AA-configuration!!!
+# 8) atm and nohyst patches (http://ace-host.stuart.id.au/russell/files/tc/tc-atm/)
+
+# This script can be edited to support more than one ADSL line.
+# Each WAN-line is shaped independently -- not quite fair, but the easiest
+# (probably the only) way to do it.
+
+# Script parameters:
+# stop removes QOS setup
+# ...any other... removes QOS setup if any, then sets new QOS.
+
+# debug on....comment out if you want BASH script debugging off
+# set -x
+
+# load configuration from external file
+. /etc/qos/config
+
+
+############# Functions for each ADSL line ######################
+function REMOVE-QOS
+{
+ local IFACE=$1 # e.g. eth0
+ local DWIMQ=$2 # e.g. 0
+
+ $TC qdisc del dev imq$DWIMQ root &> /dev/null
+ $TC qdisc del dev $IFACE root &> /dev/null
+
+ $IPTABLES -t mangle -D PREROUTING -i $IFACE -j IMQ --todev $DWIMQ &> /dev/null
+ $IP link set imq$DWIMQ down &> /dev/null
+}
+#-----------------------------------------------------------------
+function QOS-UPLINK
+{
+ local IFACE=$1
+ local UPLIMIT=$2
+ local WRR_CLIENTS=$3
+ local OVERHEAD=$4
+ local PUBIP=$5
+
+ # more description below at QOS-DOWNLINK
+
+ # The effect of these settings:
+ # - the maximum priority is 10x minimum.
+ # - it takes 25 hours without activity to gain maximum priority
+ # - it takes 90 Mbyte transferred data to be bumped to mimimum priority
+
+ local WRR_WEIGHT1_MODE=1
+ local WRR_WEIGHT1_INCR=0.00001
+ local WRR_WEIGHT1_DECR=0.00000001
+ local WRR_WEIGHT1_MIN=0.1
+ local WRR_WEIGHT1_MAX=1.0
+ local WRR_WEIGHT1_VAL=1.0
+
+ # Use HTB to limit the total speed
+ $TC qdisc add dev $IFACE root handle 8000: htb default 12
+ $TC class add dev $IFACE parent 8000: classid 8000:1 htb \
+ rate ${UPLIMIT}kbit ceil ${UPLIMIT}kbit overhead $OVERHEAD atm nohyst
+
+ # Create 3 HTB classes for high priority local, normal priority local,
+ # and normal priority client traffic.
+ $TC class add dev $IFACE parent 8000:1 classid 8000:10 htb\
+ rate $[$UPLIMIT/3]kbit ceil ${UPLIMIT}kbit overhead $OVERHEAD atm nohyst prio 2
+ $TC class add dev $IFACE parent 8000:1 classid 8000:11 htb \
+ rate $[$UPLIMIT/3]kbit ceil ${UPLIMIT}kbit overhead $OVERHEAD atm nohyst prio 1
+ $TC class add dev $IFACE parent 8000:1 classid 8000:12 htb \
+ rate $[$UPLIMIT/3]kbit ceil ${UPLIMIT}kbit overhead $OVERHEAD atm nohyst prio 1
+
+ # To distinguish between local packet and packets originating from the lan, we have
+ # told Shorewall to give the latter mark 1. (IP source cannot be used, because we are now
+ # operating after NAT, so everything has our public IP as source).
+ # Put local packets < 512 bytes in 8000:10
+ $TC filter add dev $IFACE protocol ip parent 8000:0 prio 1 u32 \
+ match mark 0 0xffff match u16 0x0000 0xfe00 at 2 flowid 8000:10
+ # Put other local packets in 8000:11
+ $TC filter add dev $IFACE protocol ip parent 8000:0 prio 1 u32 \
+ match mark 0 0xffff flowid 8000:11
+ # Non-local packets defaults to 8000:12
+
+ # Client traffic is shared according to ip-address by WRR (the masqueraded source address)
+ $TC qdisc add dev $IFACE parent 8000:12 handle 1000: wrr sour masq $WRR_CLIENTS 0
+ $TC qdisc change handle 1000: dev $IFACE wrr qdisc wmode1=$WRR_WEIGHT1_MODE wmode2=0
+
+ # Each WRR class gets a RED queue.
+ # RED drops or ECN-marks packets according to queue-length.
+ # At <=2kbyte the chance of a RED action is 0%. At 100kbyte it is 100%.
+ # Hopefully, the sender will get the picture at around 15kbytes.
+ local RED_MIN=2000 # Start shaping if average queue exceeds 2 kbyte
+ local RED_MAX=100000 # Full shaping at 100kbytes
+ local RED_LIMIT=100000 # Absolut maximum queue size
+ local RED_PROB=1.0 # The probability of dropping/marking a packet when
+ # queue >= max. Man-page suggests 0.01 or 0.02
+ local RED_AVPKT=500 # man-page suggests 1000
+ local RED_BURST=8 # man-page suggests (min+min+max)/(3*avpkt)
+ # (but they use min and max a lot differently than we do).
+
+ for LOOP in `seq 1 $WRR_CLIENTS`
+ do
+ local LOOP_HEX=$(printf %X $LOOP)
+ $TC qdisc add dev $IFACE parent 1000:$LOOP_HEX handle $[1000+$LOOP]: \
+ red probability $RED_PROB \
+ limit ${RED_LIMIT} min ${RED_MIN} max ${RED_MAX} \
+ avpkt ${RED_AVPKT} burst $RED_BURST ecn
+
+ $TC class change classid 1000:$LOOP_HEX dev $IFACE \
+ wrr min1=$WRR_WEIGHT1_MIN max1=$WRR_WEIGHT1_MAX \
+ decr1=$WRR_WEIGHT1_DECR incr1=$WRR_WEIGHT1_INCR \
+ weight1=$WRR_WEIGHT1_VAL
+ done
+}
+
+#----------------------------------------------------------------
+function QOS-DOWNLINK
+{
+ local IFACE=$1
+ local DWLIMIT=$2
+ local WRR_CLIENTS=$3
+ local OVERHEAD=$4
+ local PUBIP=$5
+
+ # The following parameters defines the way heavy downloaders are gradually
+ # given a lesser share than new downloaders (a burst effect).
+ # Each class has a weight that is dynamically modified as follows:
+ # (Actually, there are two identical sets of parameters, but I can see absolutely
+ # no reason to use the second, so it's always inactive).
+
+ # The effect of these settings:
+ # - the maximum priority is 10x minimum.
+ # - it takes 25 hours without activity to gain maximum priority
+ # - it takes 900 Mbyte transferred data to be bumped to mimimum priority
+
+ local WRR_WEIGHT1_MODE=1
+ # 0: The weight parameter is not modified
+ # 1: The weight parameter is decremented by decr*<packet size>
+ # 2: As if wmode is 1, but also multiply with number of machines waiting
+ # to transfer data
+ # 3: As if wmode is 1, but multiplied with the sum of the priorities of the
+ # machines waiting divided by the priority of this machine.
+
+ local WRR_WEIGHT1_INCR=0.00001
+ # Every second the weight parameter is incremented by this value. If
+ # weight1 reaches 1.0 it is not incremented further.
+ # The default value is 0.0.
+
+ local WRR_WEIGHT1_DECR=0.000000001
+ # Every time a packet is sent the weight parameter is modified depending
+ # on the value of wmode for the qdisc
+
+ local WRR_WEIGHT1_MIN=0.1
+ # min: (0<min)
+ # This is a lower bound for weight.
+ # The default value for this parameter is 1.0.
+
+ local WRR_WEIGHT1_MAX=1.0
+ # max: (0<max)
+ # This is a upper bound for weight.
+ # The default value for this parameter is 1.0.
+
+ local WRR_WEIGHT1_VAL=1.0
+ # weight: (min<=weight<=1.0)
+ # As mentioned above the used weight of the class is proportional to
+ # this value. The default value is 1.0.
+
+ # Use HTB to limit the speed
+ $TC qdisc add dev $IFACE root handle 8000: htb default 12
+ $TC class add dev $IFACE parent 8000: classid 8000:1 htb \
+ rate ${DWLIMIT}kbit ceil ${DWLIMIT}kbit overhead $OVERHEAD atm nohyst
+
+ # Create 3 HTB classes for high priority local, normal priority local,
+ # and normal priority client traffic.
+ $TC class add dev $IFACE parent 8000:1 classid 8000:10 htb\
+ rate $[$DWLIMIT/3]kbit ceil ${DWLIMIT}kbit overhead $OVERHEAD atm nohyst prio 2
+ $TC class add dev $IFACE parent 8000:1 classid 8000:11 htb \
+ rate $[$DWLIMIT/3]kbit ceil ${DWLIMIT}kbit overhead $OVERHEAD atm nohyst prio 1
+ $TC class add dev $IFACE parent 8000:1 classid 8000:12 htb \
+ rate $[$DWLIMIT/3]kbit ceil ${DWLIMIT}kbit overhead $OVERHEAD atm nohyst prio 1
+
+ # Put local packets < 512 bytes in 8000:10
+ # (IMQ in AA configuration grabs the packets after NAT, so we can test on destination).
+ $TC filter add dev $IFACE protocol ip parent 8000:0 prio 1 u32 \
+ match ip dst $PUBIP match u16 0x0000 0xfe00 at 2 flowid 8000:10
+
+ # Put other local packets in 8000:11
+ $TC filter add dev $IFACE protocol ip parent 8000:0 prio 1 u32 \
+ match ip dst $PUBIP flowid 8000:11
+ # Non-local packets defaults to 8000:12
+
+ # Share according to ip-address by WRR
+ $TC qdisc add dev $IFACE parent 8000:12 handle 1000: wrr dest ip $WRR_CLIENTS 0
+ $TC qdisc change handle 1000: dev $IFACE wrr qdisc wmode1=$WRR_WEIGHT1_MODE wmode2=0
+
+ # Each WRR class gets a RED queue.
+ # RED drops or ECN-marks packets according to queue-length.
+ # At 2kbyte the chance of a RED action is 0%. At 1Mbyte it is 100%.
+ # Hopefully, the sender will get the picture at around 10-20kbytes.
+ local RED_MIN=2000 # Start shaping if average queue exceeds 1 kbyte
+ local RED_MAX=1000000 # Full shaping at 1Mbytes
+ local RED_LIMIT=1000000 # Absolut maximum queue size
+ local RED_PROB=1.0 # The probability of dropping/marking a packet when
+ # queue >= max. Man-page suggests 0.01 or 0.02
+ local RED_AVPKT=1000 # man-page suggests 1000
+ local RED_BURST=2 # man-page suggests (min+min+max)/(3*avpkt)
+ # (but they use min and max a lot differently than we do).
+
+ for LOOP in `seq 1 $WRR_CLIENTS`
+ do
+ local LOOP_HEX=$(printf %X $LOOP)
+ $TC qdisc add dev $IFACE parent 1000:$LOOP_HEX handle $[1000+$LOOP]: \
+ red probability $RED_PROB \
+ limit ${RED_LIMIT} min ${RED_MIN} max ${RED_MAX} \
+ avpkt ${RED_AVPKT} burst $RED_BURST ecn
+
+ $TC class change classid 1000:$LOOP_HEX dev $IFACE \
+ wrr min1=$WRR_WEIGHT1_MIN max1=$WRR_WEIGHT1_MAX \
+ decr1=$WRR_WEIGHT1_DECR incr1=$WRR_WEIGHT1_INCR \
+ weight1=$WRR_WEIGHT1_VAL
+ done
+}
+#-----------------------------------------------------------------------
+function IFACE-SETUP
+{
+ local IFACE=$1
+ local DWIMQ=$2
+
+ $IPTABLES -t mangle -I PREROUTING -i $IFACE -j IMQ --todev $DWIMQ
+ $IP link set imq$DWIMQ up
+}
+
+##############################################################################
+
+############## Remove QOS configuration ##########################
+
+REMOVE-QOS $IF1 0 # Once for each ADSL-line
+# REMOVE-QOS $IF2 1
+
+# removing imq (version 2.6.14-imq1) causes kernel panic
+#$MODPROBE -r imq &> /dev/null
+
+if ( [ "$1" = "stop" ] )
+then
+ exit
+fi
+
+############## Set up QOS configuration ###########################
+
+$MODPROBE imq numdevs=$LINES
+
+QOS-UPLINK $IF1 $UPLIMIT1 $CLIENTS $UPOVERHEAD1 $PUBLICIP1 # Once for each ADSL-line
+# QOS-UPLINK $IF2 $UPLIMIT2 $CLIENTS $UPOVERHEAD2 $PUBLICIP2
+
+QOS-DOWNLINK imq0 $DWLIMIT1 $CLIENTS $DWOVERHEAD1 $PUBLICIP1 # Once for each ADSL-line
+# QOS-DOWNLINK imq1 $DWLIMIT2 $CLIENTS $DWOVERHEAD2 $PUBLICIP2
+
+IFACE-SETUP $IF1 0 # Once for each ADSL-line
+# IFACE-SETUP $IF2 1