#!/sbin/runscript depend() { # shaping needs the network interface the shaping is working on. need net } start() { # display to the user what you're doing ebegin "Starting Shaping on $DEV" # clean existing down- and uplink qdiscs, hide errors tc_clean tc_class eend $? } stop() { # display a message to the user ebegin "Stopping Shaping on $DEV" # output success or failure tc_clean eend } status() { tc_status } tc_clean() { # 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 } tc_status() { tc -s qdisc ls dev $DEV tc -s class ls dev $DEV tc -s filter show dev $DEV } tc_class() { # Find device MTU DEVMTU=`ifconfig $DEV | grep MTU | cut -d ':' -f 2- | sed 's/ .*//'` # Install root HTBs, point default traffic to 1:30 (Silver Class) tc qdisc add dev $DEV root handle 1: htb default 30 tc class add dev $DEV parent 1: classid 1:1 htb rate ${LANLINK}kbit \ burst ${UPLINK}kbit cburst ${UPLINK}kbit quantum $[$DEVMTU*9] \ mtu $DEVMTU ### Assured Forwarding Classes # Premium Class 1:10 tc class add dev $DEV parent 1:1 classid 1:10 htb rate $[$PREMIUM*$UPLINK/100]kbit \ prio 1 ceil ${UPLINK}kbit burst $[$PREMIUM*$UPLINK/100]kbit quantum $[$DEVMTU*6] \ mtu $DEVMTU # Gold Class 1:20 tc class add dev $DEV parent 1:1 classid 1:20 htb rate $[$GOLD*$UPLINK/100]kbit \ prio 2 ceil $[$LGOLD*$UPLINK/100]kbit quantum $[$DEVMTU*3] mtu $DEVMTU # Silver (default) Class 1:30 tc class add dev $DEV parent 1:1 classid 1:30 htb rate $[$SILVER*$UPLINK/100]kbit \ prio 3 ceil $[$LSILVER*$UPLINK/100]kbitkbit quantum $[$DEVMTU*1] mtu $DEVMTU # Bronze Class 1:40 tc class add dev $DEV parent 1:1 classid 1:40 htb rate $[$BRONZE*$UPLINK/100]kbit \ prio 3 ceil $[$LBRONZE*$UPLINK/100]kbit quantum $[$DEVMTU*1] mtu $DEVMTU ### Expediated Forwarding tc class add dev $DEV parent 1:1 classid 1:60 htb rate ${UPLINK}kbit \ prio 0 ceil ${UPLINK}kbit burst ${UPLINK}kbit quantum $[$DEVMTU*1] \ mtu $DEVMTU ### Hardware Speed Queue for local network control. tc class add dev $DEV parent 1:1 classid 1:50 htb rate ${LANLINK}kbit \ prio 1 quantum $[$DEVMTU*1] mtu $DEVMTU # AF classes get prio on top of sfq tc qdisc add dev $DEV parent 1:10 handle 10: prio tc qdisc add dev $DEV parent 10:1 handle 11: sfq perturb 10 tc qdisc add dev $DEV parent 10:2 handle 12: sfq perturb 10 tc qdisc add dev $DEV parent 10:3 handle 13: sfq perturb 10 tc qdisc add dev $DEV parent 1:20 handle 20: prio tc qdisc add dev $DEV parent 20:1 handle 21: sfq perturb 10 tc qdisc add dev $DEV parent 20:2 handle 22: sfq perturb 10 tc qdisc add dev $DEV parent 20:3 handle 23: sfq perturb 10 tc qdisc add dev $DEV parent 1:30 handle 30: prio tc qdisc add dev $DEV parent 30:1 handle 31: sfq perturb 10 tc qdisc add dev $DEV parent 30:2 handle 32: sfq perturb 10 tc qdisc add dev $DEV parent 30:3 handle 33: sfq perturb 10 tc qdisc add dev $DEV parent 1:40 handle 40: prio tc qdisc add dev $DEV parent 40:1 handle 41: sfq perturb 10 tc qdisc add dev $DEV parent 40:2 handle 42: sfq perturb 10 tc qdisc add dev $DEV parent 40:3 handle 43: sfq perturb 10 # EF class gets a basic fifo, as EF trafic can not be # sent out of order. tc qdisc add dev $DEV parent 1:60 handle 60: bfifo # Local network control trafic is a pfifo tc qdisc add dev $DEV parent 1:50 handle 50: pfifo ### Diffserv field filters # These filters are made slightly more complex by atempting # to ignore the ECN bits. # Legacy TOS fields are mapped to the classes. tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \ match ip tos 0x10 0xff flowid 1:10 tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \ match ip tos 0x08 0xff flowid 1:40 tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \ match ip tos 0x04 0xff flowid 1:30 tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \ match ip tos 0x02 0xff flowid 1:40 # AF, AF1 is Premium, AF2 is Gold, AF3 is Silver, # and AF4 is Bronze. Prio bands select the drop # precedence. # AF1 tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \ match ip tos 0x28 0xff flowid 1:10 tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \ match ip tos 0x30 0xff flowid 1:10 tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \ match ip tos 0x38 0xff flowid 1:10 # AF2 tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \ match ip tos 0x48 0xff flowid 1:20 tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \ match ip tos 0x50 0xff flowid 1:20 tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \ match ip tos 0x58 0xff flowid 1:20 # AF3 needs no match, as it's the default class # AF4 tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \ match ip tos 0x88 0xff flowid 1:40 tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \ match ip tos 0x90 0xff flowid 1:40 tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \ match ip tos 0x98 0xff flowid 1:40 # EF tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \ match ip tos 0xb8 0xff flowid 1:60 ### Special Mappings. # This should probably be left to iptables mangle rules. # No longer supported. To allow ping testing of PHB classes # # ICMP (ip protocol 1) in the gold class 1:10 so we # can do measurements & impress our friends: # tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \ # match ip protocol 1 0xff flowid 1:10 # To speed up downloads while an upload is going on, put ACK packets in # the EF class tc filter add dev $DEV parent 1: protocol ip prio 10 u32 \ match ip protocol 6 0xff \ match u8 0x05 0x0f at 0 \ match u16 0x0000 0xffc0 at 2 \ match u8 0x10 0xff at 33 \ flowid 1:60 # Everything else will default to silver class ### User mapping # Map to the apropriate field # AF 1 for a in $PREMIUMPORTDST do tc filter add dev $DEV parent 1: protocol ip prio 14 u32 \ match ip dport $a 0xffff flowid 1:10 done for a in $PREMIUMPORTSRC do tc filter add dev $DEV parent 1: protocol ip prio 15 u32 \ match ip sport $a 0xffff flowid 1:10 done for a in $PREMIUMHOSTSRC do b=`dig $a +short | sed 's/^.* //'` b=`echo $b | sed 's/^.* //'` if [ -z "$b" ] ; then b=$a ; fi #echo $b tc filter add dev $DEV parent 1: protocol ip prio 16 u32 \ match ip src $b flowid 1:10 done for a in $PREMIUMHOSTDST do b=`dig $a +short` b=`echo $b | sed 's/^.* //'` if [ -z "$b" ] ; then b=$a ; fi #echo $b tc filter add dev $DEV parent 1: protocol ip prio 17 u32 \ match ip dst $b flowid 1:10 done # AF 2 for a in $GOLDPORTDST do tc filter add dev $DEV parent 1: protocol ip prio 14 u32 \ match ip dport $a 0xffff flowid 1:10 done for a in $GOLDPORTSRC do tc filter add dev $DEV parent 1: protocol ip prio 15 u32 \ match ip sport $a 0xffff flowid 1:10 done for a in $GOLDHOSTSRC do b=`dig $a +short | sed 's/^.* //'` b=`echo $b | sed 's/^.* //'` if [ -z "$b" ] ; then b=$a ; fi #echo $b tc filter add dev $DEV parent 1: protocol ip prio 16 u32 \ match ip src $b flowid 1:10 done for a in $GOLDHOSTDST do b=`dig $a +short` b=`echo $b | sed 's/^.* //'` if [ -z "$b" ] ; then b=$a ; fi #echo $b tc filter add dev $DEV parent 1: protocol ip prio 17 u32 \ match ip dst $b flowid 1:10 done # AF 3 for a in $SILVERPORTDST do tc filter add dev $DEV parent 1: protocol ip prio 14 u32 \ match ip dport $a 0xffff flowid 1:10 done for a in $SILVERPORTSRC do tc filter add dev $DEV parent 1: protocol ip prio 15 u32 \ match ip sport $a 0xffff flowid 1:10 done for a in $SILVERHOSTSRC do b=`dig $a +short | sed 's/^.* //'` b=`echo $b | sed 's/^.* //'` if [ -z "$b" ] ; then b=$a ; fi #echo $b tc filter add dev $DEV parent 1: protocol ip prio 16 u32 \ match ip src $b flowid 1:10 done for a in $SILVERHOSTDST do b=`dig $a +short` b=`echo $b | sed 's/^.* //'` if [ -z "$b" ] ; then b=$a ; fi #echo $b tc filter add dev $DEV parent 1: protocol ip prio 17 u32 \ match ip dst $b flowid 1:10 done # AF 4 for a in $BRONZEPORTDST do tc filter add dev $DEV parent 1: protocol ip prio 14 u32 \ match ip dport $a 0xffff flowid 1:10 done for a in $BRONZEPORTSRC do tc filter add dev $DEV parent 1: protocol ip prio 15 u32 \ match ip sport $a 0xffff flowid 1:10 done for a in $BRONZEHOSTSRC do b=`dig $a +short | sed 's/^.* //'` b=`echo $b | sed 's/^.* //'` if [ -z "$b" ] ; then b=$a ; fi #echo $b tc filter add dev $DEV parent 1: protocol ip prio 16 u32 \ match ip src $b flowid 1:10 done for a in $BRONZEHOSTDST do b=`dig $a +short` b=`echo $b | sed 's/^.* //'` if [ -z "$b" ] ; then b=$a ; fi #echo $b tc filter add dev $DEV parent 1: protocol ip prio 17 u32 \ match ip dst $b flowid 1:10 done # Internal network trafic for a in $LANHOST do for b in $LANHOST do tc filter add dev $DEV parent 1: protocol ip prio 5 u32 \ match ip src $a match ip dst $b flowid 1:50 done done ### Firewall selection depricated in favour of CLASSIFY target. # # # While we pick out firewall flagged packets # tc filter add dev $DEV protocol ip parent 1:0 prio 1 handle 10 fw classid 1:10 # tc filter add dev $DEV protocol ip parent 1:0 prio 1 handle 20 fw classid 1:20 # tc filter add dev $DEV protocol ip parent 1:0 prio 1 handle 30 fw classid 1:30 # tc filter add dev $DEV protocol ip parent 1:0 prio 1 handle 50 fw classid 1:50 }