#!/bin/sh # $Id: ipshaping,v 1.5 2006/12/26 20:39:30 root Exp $ DOWNLINK=7000 UPLINK=630 DEV=outside SHARE_INTERACTIVE=50 SHARE_DEFAULT=40 SHARE_SCAVENGER=10 SHARE_BASE=$(($SHARE_INTERACTIVE + $SHARE_DEFAULT + $SHARE_SCAVENGER)) tc='/sbin/tc' stop() { # ignore errors $tc qdisc del dev $DEV root >/dev/null 2>&1 $tc qdisc del dev $DEV ingress >/dev/null 2>&1 } ingress() { $tc qdisc add dev $DEV handle ffff: ingress $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 200k drop flowid :1 } egress() { F="$tc filter add dev $DEV protocol ip parent 1:" $tc qdisc add dev $DEV root handle 1: htb default 4 r2q 5 $tc class add dev $DEV parent 1: classid 1:1 htb rate ${UPLINK}kbit ceil ${UPLINK}kbit # interactive stuff $tc class add dev $DEV parent 1:1 classid 1:2 htb burst 6k \ rate $(($SHARE_INTERACTIVE*$UPLINK/$SHARE_BASE))kbit ceil ${UPLINK}kbit prio 1 $tc qdisc add dev $DEV parent 1:2 handle 2: sfq perturb 10 # all IPTOS_LOWDELAY stuff -- i.e. ssh interactive $F prio 5 u32 match ip tos 0x10 0xff flowid 1:2 # ICMP is interactive so pings are accurate $F prio 5 u32 match ip protocol 1 0xff flowid 1:2 # dns and ntp are interactive as well $F prio 5 u32 match ip sport 53 0xffff flowid 1:2 $F prio 5 u32 match ip dport 53 0xffff flowid 1:2 $F prio 5 u32 match ip sport 123 0xffff flowid 1:2 $F prio 5 u32 match ip dport 123 0xffff flowid 1:2 # idea stolen from wshaper: ACK packets go into the interactive class # note that SACK traffic can result in >64B ACK-only packets, so the # packet size limit has been raised to 128B. $F prio 5 u32 \ match ip protocol 6 0xff \ match u8 0x05 0x0f at 0 \ match u16 0x0000 0xff80 at 2 \ match u8 0x10 0xff at 33 \ flowid 1:2 # the default class -- anything otherwise unmatched $tc class add dev $DEV parent 1:1 classid 1:3 htb burst 6k \ rate $(($SHARE_DEFAULT*$UPLINK/$SHARE_BASE))kbit ceil $((10*$UPLINK/10))kbit prio 2 $tc qdisc add dev $DEV parent 1:3 handle 3: sfq perturb 10 $F prio 10 u32 match ip dst 0.0.0.0/0 flowid 1:3 $F prio 7 u32 match ip tos 0x08 0xff match ip dport 22 0xffff flowid 1:3 # the scavenger class -- anything with IPTOS 0x20 $tc class add dev $DEV parent 1:1 classid 1:4 htb burst 6k \ rate $[$SHARE_SCAVENGER*$UPLINK/$SHARE_BASE]kbit ceil $((9*$UPLINK/10))kbit prio 3 $tc qdisc add dev $DEV parent 1:4 handle 4: sfq perturb 10 $F prio 8 u32 match ip tos 0x20 0xff flowid 1:4 $F prio 8 u32 match ip tos 0x08 0xff flowid 1:4 } case "$1" in start|restart) stop ingress egress ;; stop) stop ;; status) $tc -s qdisc ls dev $DEV $tc -s class ls dev $DEV ;; *) echo "usage: $0 start|stop|restart|status" ;; esac exit 0