summaryrefslogtreecommitdiff
path: root/localqos
blob: b969bd1d80f9b5b04d06f2ff540e351b0e4ca55f (plain)
  1. #!/bin/bash
  2. #
  3. # Shaper to share two connection more or less equally among a number of users.
  4. # By Rune Kock, rune.kock@gmail.com
  5. #
  6. # Inspired by Jim diGriz's QoS Scheduler (http://www.digriz.org.uk/jdg-qos-script/)
  7. # and by the WRR example.
  8. #
  9. # Dependencies
  10. # ------------
  11. # 1) HTB3, RED (has been in the kernel for years)
  12. # 3) iptables utility (www.netfilter.org)
  13. # 4) tc utility (developer.osdl.org/dev/iproute2)
  14. # 6) WRR patch (www.zz9.dk/wrr) and tc patch
  15. # 7) IMQ patch (www.linuximq.net) and iptables patch NOTE: in AA-configuration!!!
  16. # 8) atm and nohyst patches (http://ace-host.stuart.id.au/russell/files/tc/tc-atm/)
  17. # This script can be edited to support more than one ADSL line.
  18. # Each WAN-line is shaped independently -- not quite fair, but the easiest
  19. # (probably the only) way to do it.
  20. # Script parameters:
  21. # stop removes QOS setup
  22. # ...any other... removes QOS setup if any, then sets new QOS.
  23. # debug on....comment out if you want BASH script debugging off
  24. # set -x
  25. # load configuration from external file
  26. . /etc/qos/config
  27. ############# Functions for each ADSL line ######################
  28. function REMOVE-QOS
  29. {
  30. local IFACE=$1 # e.g. eth0
  31. local DWIMQ=$2 # e.g. 0
  32. $TC qdisc del dev imq$DWIMQ root &> /dev/null
  33. $TC qdisc del dev $IFACE root &> /dev/null
  34. $IPTABLES -t mangle -D PREROUTING -i $IFACE -j IMQ --todev $DWIMQ &> /dev/null
  35. $IP link set imq$DWIMQ down &> /dev/null
  36. }
  37. #-----------------------------------------------------------------
  38. function QOS-UPLINK
  39. {
  40. local IFACE=$1
  41. local UPLIMIT=$2
  42. local WRR_CLIENTS=$3
  43. local OVERHEAD=$4
  44. local PUBIP=$5
  45. # more description below at QOS-DOWNLINK
  46. # The effect of these settings:
  47. # - the maximum priority is 10x minimum.
  48. # - it takes 25 hours without activity to gain maximum priority
  49. # - it takes 90 Mbyte transferred data to be bumped to mimimum priority
  50. local WRR_WEIGHT1_MODE=1
  51. local WRR_WEIGHT1_INCR=0.00001
  52. local WRR_WEIGHT1_DECR=0.00000001
  53. local WRR_WEIGHT1_MIN=0.1
  54. local WRR_WEIGHT1_MAX=1.0
  55. local WRR_WEIGHT1_VAL=1.0
  56. # Use HTB to limit the total speed
  57. $TC qdisc add dev $IFACE root handle 8000: htb default 12
  58. $TC class add dev $IFACE parent 8000: classid 8000:1 htb \
  59. rate ${UPLIMIT}kbit ceil ${UPLIMIT}kbit overhead $OVERHEAD atm nohyst
  60. # Create 3 HTB classes for high priority local, normal priority local,
  61. # and normal priority client traffic.
  62. $TC class add dev $IFACE parent 8000:1 classid 8000:10 htb\
  63. rate $[$UPLIMIT/3]kbit ceil ${UPLIMIT}kbit overhead $OVERHEAD atm nohyst prio 2
  64. $TC class add dev $IFACE parent 8000:1 classid 8000:11 htb \
  65. rate $[$UPLIMIT/3]kbit ceil ${UPLIMIT}kbit overhead $OVERHEAD atm nohyst prio 1
  66. $TC class add dev $IFACE parent 8000:1 classid 8000:12 htb \
  67. rate $[$UPLIMIT/3]kbit ceil ${UPLIMIT}kbit overhead $OVERHEAD atm nohyst prio 1
  68. # To distinguish between local packet and packets originating from the lan, we have
  69. # told Shorewall to give the latter mark 1. (IP source cannot be used, because we are now
  70. # operating after NAT, so everything has our public IP as source).
  71. # Put local packets < 512 bytes in 8000:10
  72. $TC filter add dev $IFACE protocol ip parent 8000:0 prio 1 u32 \
  73. match mark 0 0xffff match u16 0x0000 0xfe00 at 2 flowid 8000:10
  74. # Put other local packets in 8000:11
  75. $TC filter add dev $IFACE protocol ip parent 8000:0 prio 1 u32 \
  76. match mark 0 0xffff flowid 8000:11
  77. # Non-local packets defaults to 8000:12
  78. # Client traffic is shared according to ip-address by WRR (the masqueraded source address)
  79. $TC qdisc add dev $IFACE parent 8000:12 handle 1000: wrr sour masq $WRR_CLIENTS 0
  80. $TC qdisc change handle 1000: dev $IFACE wrr qdisc wmode1=$WRR_WEIGHT1_MODE wmode2=0
  81. # Each WRR class gets a RED queue.
  82. # RED drops or ECN-marks packets according to queue-length.
  83. # At <=2kbyte the chance of a RED action is 0%. At 100kbyte it is 100%.
  84. # Hopefully, the sender will get the picture at around 15kbytes.
  85. local RED_MIN=2000 # Start shaping if average queue exceeds 2 kbyte
  86. local RED_MAX=100000 # Full shaping at 100kbytes
  87. local RED_LIMIT=100000 # Absolut maximum queue size
  88. local RED_PROB=1.0 # The probability of dropping/marking a packet when
  89. # queue >= max. Man-page suggests 0.01 or 0.02
  90. local RED_AVPKT=500 # man-page suggests 1000
  91. local RED_BURST=8 # man-page suggests (min+min+max)/(3*avpkt)
  92. # (but they use min and max a lot differently than we do).
  93. for LOOP in `seq 1 $WRR_CLIENTS`
  94. do
  95. local LOOP_HEX=$(printf %X $LOOP)
  96. $TC qdisc add dev $IFACE parent 1000:$LOOP_HEX handle $[1000+$LOOP]: \
  97. red probability $RED_PROB \
  98. limit ${RED_LIMIT} min ${RED_MIN} max ${RED_MAX} \
  99. avpkt ${RED_AVPKT} burst $RED_BURST ecn
  100. $TC class change classid 1000:$LOOP_HEX dev $IFACE \
  101. wrr min1=$WRR_WEIGHT1_MIN max1=$WRR_WEIGHT1_MAX \
  102. decr1=$WRR_WEIGHT1_DECR incr1=$WRR_WEIGHT1_INCR \
  103. weight1=$WRR_WEIGHT1_VAL
  104. done
  105. }
  106. #----------------------------------------------------------------
  107. function QOS-DOWNLINK
  108. {
  109. local IFACE=$1
  110. local DWLIMIT=$2
  111. local WRR_CLIENTS=$3
  112. local OVERHEAD=$4
  113. local PUBIP=$5
  114. # The following parameters defines the way heavy downloaders are gradually
  115. # given a lesser share than new downloaders (a burst effect).
  116. # Each class has a weight that is dynamically modified as follows:
  117. # (Actually, there are two identical sets of parameters, but I can see absolutely
  118. # no reason to use the second, so it's always inactive).
  119. # The effect of these settings:
  120. # - the maximum priority is 10x minimum.
  121. # - it takes 25 hours without activity to gain maximum priority
  122. # - it takes 900 Mbyte transferred data to be bumped to mimimum priority
  123. local WRR_WEIGHT1_MODE=1
  124. # 0: The weight parameter is not modified
  125. # 1: The weight parameter is decremented by decr*<packet size>
  126. # 2: As if wmode is 1, but also multiply with number of machines waiting
  127. # to transfer data
  128. # 3: As if wmode is 1, but multiplied with the sum of the priorities of the
  129. # machines waiting divided by the priority of this machine.
  130. local WRR_WEIGHT1_INCR=0.00001
  131. # Every second the weight parameter is incremented by this value. If
  132. # weight1 reaches 1.0 it is not incremented further.
  133. # The default value is 0.0.
  134. local WRR_WEIGHT1_DECR=0.000000001
  135. # Every time a packet is sent the weight parameter is modified depending
  136. # on the value of wmode for the qdisc
  137. local WRR_WEIGHT1_MIN=0.1
  138. # min: (0<min)
  139. # This is a lower bound for weight.
  140. # The default value for this parameter is 1.0.
  141. local WRR_WEIGHT1_MAX=1.0
  142. # max: (0<max)
  143. # This is a upper bound for weight.
  144. # The default value for this parameter is 1.0.
  145. local WRR_WEIGHT1_VAL=1.0
  146. # weight: (min<=weight<=1.0)
  147. # As mentioned above the used weight of the class is proportional to
  148. # this value. The default value is 1.0.
  149. # Use HTB to limit the speed
  150. $TC qdisc add dev $IFACE root handle 8000: htb default 12
  151. $TC class add dev $IFACE parent 8000: classid 8000:1 htb \
  152. rate ${DWLIMIT}kbit ceil ${DWLIMIT}kbit overhead $OVERHEAD atm nohyst
  153. # Create 3 HTB classes for high priority local, normal priority local,
  154. # and normal priority client traffic.
  155. $TC class add dev $IFACE parent 8000:1 classid 8000:10 htb\
  156. rate $[$DWLIMIT/3]kbit ceil ${DWLIMIT}kbit overhead $OVERHEAD atm nohyst prio 2
  157. $TC class add dev $IFACE parent 8000:1 classid 8000:11 htb \
  158. rate $[$DWLIMIT/3]kbit ceil ${DWLIMIT}kbit overhead $OVERHEAD atm nohyst prio 1
  159. $TC class add dev $IFACE parent 8000:1 classid 8000:12 htb \
  160. rate $[$DWLIMIT/3]kbit ceil ${DWLIMIT}kbit overhead $OVERHEAD atm nohyst prio 1
  161. # Put local packets < 512 bytes in 8000:10
  162. # (IMQ in AA configuration grabs the packets after NAT, so we can test on destination).
  163. $TC filter add dev $IFACE protocol ip parent 8000:0 prio 1 u32 \
  164. match ip dst $PUBIP match u16 0x0000 0xfe00 at 2 flowid 8000:10
  165. # Put other local packets in 8000:11
  166. $TC filter add dev $IFACE protocol ip parent 8000:0 prio 1 u32 \
  167. match ip dst $PUBIP flowid 8000:11
  168. # Non-local packets defaults to 8000:12
  169. # Share according to ip-address by WRR
  170. $TC qdisc add dev $IFACE parent 8000:12 handle 1000: wrr dest ip $WRR_CLIENTS 0
  171. $TC qdisc change handle 1000: dev $IFACE wrr qdisc wmode1=$WRR_WEIGHT1_MODE wmode2=0
  172. # Each WRR class gets a RED queue.
  173. # RED drops or ECN-marks packets according to queue-length.
  174. # At 2kbyte the chance of a RED action is 0%. At 1Mbyte it is 100%.
  175. # Hopefully, the sender will get the picture at around 10-20kbytes.
  176. local RED_MIN=2000 # Start shaping if average queue exceeds 1 kbyte
  177. local RED_MAX=1000000 # Full shaping at 1Mbytes
  178. local RED_LIMIT=1000000 # Absolut maximum queue size
  179. local RED_PROB=1.0 # The probability of dropping/marking a packet when
  180. # queue >= max. Man-page suggests 0.01 or 0.02
  181. local RED_AVPKT=1000 # man-page suggests 1000
  182. local RED_BURST=2 # man-page suggests (min+min+max)/(3*avpkt)
  183. # (but they use min and max a lot differently than we do).
  184. for LOOP in `seq 1 $WRR_CLIENTS`
  185. do
  186. local LOOP_HEX=$(printf %X $LOOP)
  187. $TC qdisc add dev $IFACE parent 1000:$LOOP_HEX handle $[1000+$LOOP]: \
  188. red probability $RED_PROB \
  189. limit ${RED_LIMIT} min ${RED_MIN} max ${RED_MAX} \
  190. avpkt ${RED_AVPKT} burst $RED_BURST ecn
  191. $TC class change classid 1000:$LOOP_HEX dev $IFACE \
  192. wrr min1=$WRR_WEIGHT1_MIN max1=$WRR_WEIGHT1_MAX \
  193. decr1=$WRR_WEIGHT1_DECR incr1=$WRR_WEIGHT1_INCR \
  194. weight1=$WRR_WEIGHT1_VAL
  195. done
  196. }
  197. #-----------------------------------------------------------------------
  198. function IFACE-SETUP
  199. {
  200. local IFACE=$1
  201. local DWIMQ=$2
  202. $IPTABLES -t mangle -I PREROUTING -i $IFACE -j IMQ --todev $DWIMQ
  203. $IP link set imq$DWIMQ up
  204. }
  205. ##############################################################################
  206. ############## Remove QOS configuration ##########################
  207. REMOVE-QOS $IF1 0 # Once for each ADSL-line
  208. # REMOVE-QOS $IF2 1
  209. # removing imq (version 2.6.14-imq1) causes kernel panic
  210. #$MODPROBE -r imq &> /dev/null
  211. if ( [ "$1" = "stop" ] )
  212. then
  213. exit
  214. fi
  215. ############## Set up QOS configuration ###########################
  216. $MODPROBE imq numdevs=$LINES
  217. QOS-UPLINK $IF1 $UPLIMIT1 $CLIENTS $UPOVERHEAD1 $PUBLICIP1 # Once for each ADSL-line
  218. # QOS-UPLINK $IF2 $UPLIMIT2 $CLIENTS $UPOVERHEAD2 $PUBLICIP2
  219. QOS-DOWNLINK imq0 $DWLIMIT1 $CLIENTS $DWOVERHEAD1 $PUBLICIP1 # Once for each ADSL-line
  220. # QOS-DOWNLINK imq1 $DWLIMIT2 $CLIENTS $DWOVERHEAD2 $PUBLICIP2
  221. IFACE-SETUP $IF1 0 # Once for each ADSL-line
  222. # IFACE-SETUP $IF2 1