#!/bin/bash # # Jim diGriz's QoS Scheduler for an Ethernet Bridge # [remove 'junk-this' to mail me] # GPL V2 blar blar blar # Version: 030706 (aka 6th July 2003) # # Dependencies # 1) HTB3 patch (if <2.4.18) and 'tc' patch # 2) RED (in kernel 2.4.x) # 3) iptables (in kernel 2.4.x) # 4) ESFQ patch (http://www.ssi.bg/~alex/esfq/index.html) and 'tc' patch # # N.B. # shaping only works for OUTGOING packets simply so think which interface to us # # Changelog # [03/04/28] - Started with wondershaper-1.1a script (http://lartc.org/) # [03/04/28] - migrated using SFQ to ESFQ (for src ip hashing) # [03/04/29] - added some RED usage (downloading tcp traffic) # - fix '$[9*$UPLINK/10]kbit' for 1:20 to '$[8*$UPLINK/10]kbit' # - migration to use iptables MANGLE rather than using 'tc filter' # by using the ADSL-Bandwidth-Management-HOWTO for reference # - migration to not use ingress # [03/07/06] - tweaked values, convinced myself that 15% bandwidth was lost # due to header overhead and trimmed a further 5% to clear # buffers. Tweaked the download link, as ESFQ was set to 'src' # instead of 'dst' and made RED use the $(DW/IP)IFLIMIT values. # result in non-fluctuating ping and RED is now working. # Also added support to exclude 'local' traffic. Fixed various # bugs where traffic was not going to their correct queues. # Note that if you have no 'private' addresses (I have linux # running as a ethernet brdige and so its on a private IP) you # can leave the LOCAL_TRAFFIC section alone # TODO: # 1) more iptable mangle rules # 2) tweak iptables rules # 3) add support for IPMasq # 4) support to ignore LOCAL_TRAFFIC if need be # Useful Info # IPTables TOS Fields: # Minimize-Delay 16 (0x10) # Maximize-Throughput 8 (0x08) # Maximize-Reliability 4 (0x04) # Minimize-Cost 2 (0x02), # Normal-Service 0 (0x00). # debug on.... #set -x # ballpark configuration details (all in kbit) DWIF=eth1 # WAN facing interface DWIFLIMIT=1638 # 2048*0.8 UPIF=eth0 # LAN facing interface UPIFSPEED=100000 # speed of LAN card UPIFLIMIT=204 # 256*0.8 LOCAL_TRAFFIC=192.168.0.0/16 # 'local' LAN addresses if [ "$1" = "status" ] then tc -s qdisc ls dev $DWIF tc -s qdisc ls dev $UPIF exit fi if [ "$1" = "pollstatus" ] then watch -n1 'tc -s qdisc show dev eth0; echo "--------"; tc -s qdisc show dev eth1' exit fi # clean existing down and uplink qdiscs, hide errors tc qdisc del dev $DWIF root &> /dev/null tc qdisc del dev $UPIF root &> /dev/null iptables -t mangle -D POSTROUTING -o $UPIF -j SHAPER-OUT &> /dev/null iptables -t mangle -F SHAPER-OUT &> /dev/null iptables -t mangle -X SHAPER-OUT &> /dev/null iptables -t mangle -D POSTROUTING -o $DWIF -j SHAPER-IN &> /dev/null iptables -t mangle -F SHAPER-IN &> /dev/null iptables -t mangle -X SHAPER-IN &> /dev/null iptables -t mangle -F chkack &> /dev/null iptables -t mangle -X chkack &> /dev/null if [ "$1" = "stop" ] then exit fi ############# configuring QoS system ###################### ###### uplink # install root HTB, point default traffic to 1:27: tc qdisc add dev $UPIF root handle 1: htb default 27 tc class add dev $UPIF parent 1:1 classid 1:2 htb rate ${UPIFLIMIT}kbit # shape everything at $UPIFLIMIT speed - this prevents huge queues in your # DSL modem which destroy latency: # high prio class 1:20 to low prio class 1:29: tc class add dev $UPIF parent 1:2 classid 1:20 htb rate $[5*$UPIFLIMIT/10]kbit \ ceil ${UPIFLIMIT}kbit burst 6k prio 0 tc class add dev $UPIF parent 1:2 classid 1:21 htb rate $[5*$UPIFLIMIT/10]kbit \ ceil ${UPIFLIMIT}kbit burst 6k prio 1 tc class add dev $UPIF parent 1:2 classid 1:22 htb rate $[4*$UPIFLIMIT/10]kbit \ ceil ${UPIFLIMIT}kbit burst 6k prio 2 tc class add dev $UPIF parent 1:2 classid 1:23 htb rate $[4*$UPIFLIMIT/10]kbit \ ceil ${UPIFLIMIT}kbit burst 6k prio 3 tc class add dev $UPIF parent 1:2 classid 1:24 htb rate $[3*$UPIFLIMIT/10]kbit \ ceil ${UPIFLIMIT}kbit burst 6k prio 4 tc class add dev $UPIF parent 1:2 classid 1:25 htb rate $[3*$UPIFLIMIT/10]kbit \ ceil ${UPIFLIMIT}kbit burst 6k prio 5 tc class add dev $UPIF parent 1:2 classid 1:26 htb rate $[2*$UPIFLIMIT/10]kbit \ ceil ${UPIFLIMIT}kbit burst 6k prio 6 tc class add dev $UPIF parent 1:2 classid 1:27 htb rate $[2*$UPIFLIMIT/10]kbit \ ceil ${UPIFLIMIT}kbit burst 6k prio 7 tc class add dev $UPIF parent 1:2 classid 1:28 htb rate $[1*$UPIFLIMIT/10]kbit \ ceil ${UPIFLIMIT}kbit burst 6k prio 8 tc class add dev $UPIF parent 1:2 classid 1:29 htb rate $[1*$UPIFLIMIT/10]kbit \ ceil ${UPIFLIMIT}kbit burst 6k prio 9 # all get Enchanced Stochastic Fairness (depending on src ip): tc qdisc add dev $UPIF parent 1:20 handle 20: esfq perturb 10 hash src tc qdisc add dev $UPIF parent 1:21 handle 21: esfq perturb 10 hash src tc qdisc add dev $UPIF parent 1:22 handle 22: esfq perturb 10 hash src tc qdisc add dev $UPIF parent 1:23 handle 23: esfq perturb 10 hash src tc qdisc add dev $UPIF parent 1:24 handle 24: esfq perturb 10 hash src tc qdisc add dev $UPIF parent 1:25 handle 25: esfq perturb 10 hash src tc qdisc add dev $UPIF parent 1:26 handle 26: esfq perturb 10 hash src tc qdisc add dev $UPIF parent 1:27 handle 27: esfq perturb 10 hash src tc qdisc add dev $UPIF parent 1:28 handle 28: esfq perturb 10 hash src tc qdisc add dev $UPIF parent 1:29 handle 29: esfq perturb 10 hash src # setup iptables hooks tc filter add dev $UPIF parent 1: prio 0 protocol ip handle 20 fw flowid 1:20 tc filter add dev $UPIF parent 1: prio 0 protocol ip handle 21 fw flowid 1:21 tc filter add dev $UPIF parent 1: prio 0 protocol ip handle 22 fw flowid 1:22 tc filter add dev $UPIF parent 1: prio 0 protocol ip handle 23 fw flowid 1:23 tc filter add dev $UPIF parent 1: prio 0 protocol ip handle 24 fw flowid 1:24 tc filter add dev $UPIF parent 1: prio 0 protocol ip handle 25 fw flowid 1:25 tc filter add dev $UPIF parent 1: prio 0 protocol ip handle 26 fw flowid 1:26 tc filter add dev $UPIF parent 1: prio 0 protocol ip handle 27 fw flowid 1:27 tc filter add dev $UPIF parent 1: prio 0 protocol ip handle 28 fw flowid 1:28 tc filter add dev $UPIF parent 1: prio 0 protocol ip handle 29 fw flowid 1:29 tc filter add dev $UPIF parent 1: prio 0 protocol ip handle 9999 fw flowid 1: iptables -t mangle -N SHAPER-OUT iptables -t mangle -I POSTROUTING -o $UPIF -j SHAPER-OUT ########## 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 # tc qdisc add dev $DWIF root handle 1: htb default 21 tc class add dev $DWIF parent 1: classid 1:1 htb rate ${DWIFLIMIT}kbit tc class add dev $DWIF parent 1:1 classid 1:20 htb rate $[$DWIFLIMIT/2]kbit \ ceil ${DWIFLIMIT}kbit burst 6k prio 0 tc class add dev $DWIF parent 1:1 classid 1:21 htb rate $[$DWIFLIMIT/2]kbit \ ceil ${DWIFLIMIT}kbit burst 6k prio 1 tc qdisc add dev $DWIF parent 1:20 handle 20: esfq perturb 10 hash dst # ---- RED_MIN=$[$DWIFLIMIT*1000/8/4] # starts dropping at 25% bandwidth RED_MAX=$[$DWIFLIMIT*1000/8] RED_LIMIT=$[$RED_MAX*2] RED_AVPKT=1000 # ---- tc qdisc add dev $DWIF parent 1:21 handle 21: red \ probability 1.00 limit ${RED_LIMIT} min ${RED_MIN} max ${RED_MAX} \ avpkt ${RED_AVPKT} burst $[((2*$RED_MIN)+($RED_MAX))/(3*$RED_AVPKT)] tc filter add dev $DWIF parent 1: prio 0 protocol ip handle 20 fw flowid 1:20 tc filter add dev $DWIF parent 1: prio 0 protocol ip handle 21 fw flowid 1:21 tc filter add dev $DWIF parent 1: prio 0 protocol ip handle 9999 fw flowid 1: iptables -t mangle -N SHAPER-IN iptables -t mangle -I POSTROUTING -o $DWIF -j SHAPER-IN ################## finish QoS configuration ######################### ################# begin packet classification ####################### # upload (20->29) #--------- Track those P2P ACK packets...... iptables -t mangle -N chkack iptables -t mangle -A chkack -m tos --tos ! Normal-Service -j RETURN iptables -t mangle -A chkack -p tcp -m length --length :128 -j TOS --set-tos Minimize-Delay iptables -t mangle -A chkack -p tcp -m length --length 128: -j TOS --set-tos Maximize-Throughput iptables -t mangle -A chkack -j RETURN #-------- iptables -t mangle -A SHAPER-OUT -p tcp -m tcp --tcp-flags SYN,RST,ACK ACK -j chkack iptables -t mangle -A SHAPER-OUT -p icmp -j MARK --set-mark 20 # icmp (ping) iptables -t mangle -A SHAPER-OUT -p tcp --sport :1024 -j MARK --set-mark 25 iptables -t mangle -A SHAPER-OUT -p tcp --dport :1024 -j MARK --set-mark 25 iptables -t mangle -A SHAPER-OUT -p tcp -m tos --tos Minimize-Delay -j MARK --set-mark 23 iptables -t mangle -A SHAPER-OUT -p tcp --dport ssh -j MARK --set-mark 22 # ssh iptables -t mangle -A SHAPER-OUT -p tcp --sport ssh -j MARK --set-mark 22 # ssh iptables -t mangle -A SHAPER-OUT -p tcp --dport telnet -j MARK --set-mark 22 # telnet iptables -t mangle -A SHAPER-OUT -p tcp --sport telnet -j MARK --set-mark 22 # telnet iptables -t mangle -A SHAPER-OUT -p udp -j MARK --set-mark 24 # udp traffic iptables -t mangle -A SHAPER-OUT -p tcp --sport http -j MARK --set-mark 26 # web traffic iptables -t mangle -A SHAPER-OUT -p tcp -m tos --tos Maximize-Throughput -j MARK --set-mark 29 # get ssh bulk and other bulk traffic iptables -t mangle -A SHAPER-OUT -p tcp --dport 20 -j MARK --set-mark 29 # (ftp data) iptables -t mangle -A SHAPER-OUT -m mark --mark 0 -j MARK --set-mark 27 # default iptables -t mangle -A SHAPER-OUT -s ${LOCAL_TRAFFIC} -j MARK --set-mark 9999 # no shaping for local iptables -t mangle -A SHAPER-OUT -d ${LOCAL_TRAFFIC} -j MARK --set-mark 9999 # no shaping for local # download (20->21) iptables -t mangle -A SHAPER-IN -p ! tcp -j MARK --set-mark 20 # non-tcp traffic iptables -t mangle -A SHAPER-IN -p tcp -m length --length :64 -j MARK --set-mark 20 # short TCP packets iptables -t mangle -A SHAPER-IN -p tcp --dport ssh -j MARK --set-mark 20 # ssh iptables -t mangle -A SHAPER-IN -p tcp --sport ssh -j MARK --set-mark 20 # ssh iptables -t mangle -A SHAPER-IN -p tcp --dport telnet -j MARK --set-mark 20 # telnet iptables -t mangle -A SHAPER-IN -p tcp --sport telnet -j MARK --set-mark 20 # telnet iptables -t mangle -A SHAPER-IN -p tcp --sport ssh -m tos --tos ! Minimize-Delay -j MARK --set-mark 21 # ssh bulk iptables -t mangle -A SHAPER-IN -p tcp --dport ssh -m tos --tos ! Minimize-Delay -j MARK --set-mark 21 # ssh bulk iptables -t mangle -A SHAPER-IN -m mark --mark 0 -j MARK --set-mark 21 # default iptables -t mangle -A SHAPER-IN -s ${LOCAL_TRAFFIC} -j MARK --set-mark 9999 # no shaping for local iptables -t mangle -A SHAPER-IN -d ${LOCAL_TRAFFIC} -j MARK --set-mark 9999 # no shaping for local ################### end packet classification #######################