add tc egress shaping
authorJustin Wind <justin.wind+git@gmail.com>
Mon, 30 Jan 2017 22:50:26 +0000 (14:50 -0800)
committerJustin Wind <justin.wind+git@gmail.com>
Mon, 30 Jan 2017 22:50:26 +0000 (14:50 -0800)
common.sh
shaper.sh [new file with mode: 0755]

index f4da792d9fcdb455cd923cac167b76424c6a7b36..1e40677e555815434c10762f930e8b94af3d7a95 100644 (file)
--- a/common.sh
+++ b/common.sh
@@ -5,6 +5,7 @@ set -e
 IPTABLES=$(which iptables)
 IP6TABLES=$(which ip6tables)
 IPSET=$(which ipset)
+TC=$(which tc)
 
 err(){
        echo "$@" 1>&2
diff --git a/shaper.sh b/shaper.sh
new file mode 100755 (executable)
index 0000000..f335718
--- /dev/null
+++ b/shaper.sh
@@ -0,0 +1,86 @@
+#!/bin/sh
+
+# settings
+UPLINK=11232 #kbit
+BURST=15 #k
+SHAPE_CHAIN='SHAPER-OUT'
+#
+
+set -e
+
+. ./common.sh
+
+if [ $# -lt 1 ]
+then
+       echo "Usage: $(basename "$0") external_interface" 1>&2
+       exit 64
+fi
+
+EXT_IF="$1"
+if ! ip link show "${EXT_IF}" >/dev/null 2>&1
+then
+       echo "'${EXT_IF}' does not seem to be a valid interface"
+       exit 1
+fi
+
+function shape_if(){
+       local ext_if="$1" uplink="$2" burst="$3"
+
+       $TC qdisc del dev ${ext_if} root >/dev/null 2>&1 || true
+
+       $TC qdisc add dev ${ext_if} root handle 1: htb default 30
+       $TC class add dev ${ext_if} parent 1: classid 1:1 htb rate ${uplink}kbit burst ${burst}k
+
+       $TC class add dev ${ext_if} parent 1:1 classid 1:10 htb rate ${uplink}kbit burst ${burst}k prio 1
+       $TC class add dev ${ext_if} parent 1:1 classid 1:20 htb rate ${uplink}kbit burst ${burst}k prio 2
+       $TC class add dev ${ext_if} parent 1:1 classid 1:30 htb rate $(expr 9 \* ${uplink} / 10)kbit burst ${burst}k prio 3
+       $TC class add dev ${ext_if} parent 1:1 classid 1:40 htb rate $(expr 5 \* ${uplink} / 10)kbit burst ${burst}k prio 4
+       $TC class add dev ${ext_if} parent 1:1 classid 1:50 htb rate $(expr 5 \* ${uplink} / 10)kbit burst $(expr 2 \* ${burst} / 3)k prio 5
+
+       for x in $(seq 5)
+       do
+               # $TC qdisc add dev ${ext_if} parent 1:${x}0 handle ${x}0: sfq perturb 10
+               $TC qdisc add dev ${ext_if} parent 1:${x}0 handle ${x}0: fq_codel
+               $TC filter add dev ${ext_if} parent 1: prio 0 protocol ip handle ${x} fw flowid 1:${x}0
+       done
+}
+
+function shape(){
+       local prio="$1"
+       shift
+       if ! $IPTABLES -t mangle -C "${SHAPE_CHAIN}" "$@" -j MARK --set-mark ${prio} >/dev/null 2>&1
+       then
+               $IPTABLES -t mangle -A "${SHAPE_CHAIN}" "$@" -j MARK --set-mark ${prio}
+       fi
+}
+
+shape_if "${EXT_IF}" "${UPLINK}" "${BURST}"
+
+if ! $IPTABLES -t mangle -L "${SHAPE_CHAIN}" >/dev/null 2>&1
+then
+       echo "initializing chain '${SHAPE_CHAIN}'"
+       $IPTABLES -t mangle -N "${SHAPE_CHAIN}"
+fi
+
+shape 1 -p icmp
+shape 1 -p udp
+shape 1 -p tcp -m length --length :64
+shape 1 -p tcp --syn -m length --length 40:68
+shape 1 -p tcp --tcp-flags ALL ACK -m length --length 40:100
+shape 1 -p tcp --tcp-flags ALL RST
+shape 1 -p tcp --tcp-flags ALL ACK,RST
+shape 1 -p tcp --tcp-flags ALL ACK,FIN
+
+shape 2 -p tcp --dport 22
+
+shape 4 -p tcp --dport 20
+shape 4 -p tcp --dport 115
+
+shape 5 -p tcp --dport 8881:8899
+shape 5 -p tcp --sport 8881:8899
+
+if ! $IPTABLES -t mangle -C POSTROUTING -o "${EXT_IF}" -j "${SHAPE_CHAIN}" >/dev/null 2>&1
+then
+       $IPTABLES -t mangle -C POSTROUTING -o "${EXT_IF}" -j "${SHAPE_CHAIN}"
+fi
+