summaryrefslogtreecommitdiffstats
path: root/debloat.sh
blob: e49a1997005da4ef6e20f94f56c7bb95fc9e304b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/bin/bash
# debloat.sh -	improves network latency by reducing excessive buffering
#		and offloads on common devices and enabling fq_codel.
# Copyright 2012 M D Taht. Released into the public domain.

# This script is presently targetted to go into
# /etc/network/ifup.d on debian derived systems

[[ "$IFACE" == "lo" ]] && exit 0

LL=1 # go for lowest latency
ECN=1 # enable ECN
BQLLIMIT100=3000 # at speeds below 100Mbit, 2 big packets is enough
BQLLIMIT10=1514 # at speeds below 10Mbit, 1 big packet is enough.
		# Actually it would be nice to go to just one packet
QDISC=fq_codel # There are multiple variants of fq_codel in testing
FQ_LIMIT="" # the default 10000 packet limit mucks with slow start at speeds
            # at 1Gbit and below. Somewhat arbitrary figures selected.

[ -z "$IFACE" ] && echo error: $0 expects IFACE parameter in environment && exit 1
[ -z `which ethtool` ] && echo error: ethtool is required && exit 1
[ -z `which tc` ] && echo error: tc is required && exit 1
# FIXME see if $QDISC is available. modprobe?

# BUGS - need to detect bridges.
#      - Need filter to distribute across mq ethernet devices
#      - needs an "undebloat" script for ifdown to restore BQL autotuning

S=/sys/class/net
FQ_OPTS=""
#FQ_OPTS="FLOWS 2048 TARGET 5ms"

[ $LL -eq 1 ] && FQ_OPTS="$FQ_OPTS quantum 500"
[ $ECN -eq 1 ] && FQ_OPTS="$FQ_OPTS ecn"

FLOW_KEYS="src,dst,proto,proto-src,proto-dst"
# For 5-tuple (flow) fairness when the same device is performing NAT
#FLOW_KEYS="nfct-src,nfct-dst,nfct-proto,nfct-proto-src,nfct-proto-dst"


# Offloads are evil in the quest for low latency
# And ethtool will abort if you attempt to turn off a
# nonexistent offload.

et() {
(
	ethtool -K $IFACE tso off
	ethtool -K $IFACE gso off
	ethtool -K $IFACE ufo off
# Presently unknown if gro/lro affect latency much
	ethtool -K $IFACE gro off
	ethtool -K $IFACE lro off
) 2> /dev/null
}

# Wifi is special in that how the queues work is pre-defined
# to be voice, video, best effort and background

wifi() {
	tc qdisc add dev $IFACE handle 1 root mq
	tc qdisc add dev $IFACE parent 1:1 $QDISC $FQ_OPTS noecn
	tc qdisc add dev $IFACE parent 1:2 $QDISC $FQ_OPTS
	tc qdisc add dev $IFACE parent 1:3 $QDISC $FQ_OPTS
	tc qdisc add dev $IFACE parent 1:4 $QDISC $FQ_OPTS noecn
}

# Hardware mq ethernet devs are special and need some sort of filter
# attached to actually use in most cases. FIXME. (see tg3)

mq() {
	local I=1
	tc qdisc add dev $IFACE handle 1 root mq

	for i in $S/$IFACE/queues/tx-*
	do
		tc qdisc add dev $IFACE parent 1:$(printf "%x" $I) $QDISC $FQ_OPTS
		I=`expr $I + 1`
	done
	I=`expr $I - 1`
	tc filter add dev $IFACE prio 1 protocol ip parent 1: handle 100 \
		flow hash keys ${FLOW_KEYS} divisor $I baseclass 1:1
}

fq_codel() {
	tc qdisc add dev $IFACE root $QDISC $FQ_OPTS $FQ_LIMIT
}

fix_speed() {
local SPEED=`cat $S/$IFACE/speed` 2> /dev/null
if [ -n "$SPEED" ]
then
	[ "$SPEED" = 4294967295 ] && echo "no ethernet speed selected. debloat estimate will be WRONG"
	[ "$SPEED" -lt 1001 ] && FQ_LIMIT="limit 1200"
	if [ "$SPEED" -lt 101 ]
	then
	[ $LL -eq 1 ] && et # for lowest latency disable offloads
	BQLLIMIT=$BQLLIMIT100
	FQ_LIMIT="limit 800"
	[ "$SPEED" -lt 11 ] && BQLLIMIT=$BQLLIMIT10 && FQ_LIMIT="limit 400"
	for I in /sys/class/net/$IFACE/queues/tx-*/byte_queue_limits/limit_max
		do
			echo $BQLLIMIT > $I
		done
	fi
fi
}

fix_queues() {
local QUEUES=`ls -d $S/$IFACE/queues/tx-* | wc -l | awk '{print $1}'`
if [ $QUEUES -gt 1 ]
then
	if [ -x $S/$IFACE/phy80211 ]
	then
		wifi
	else
		mq
	fi
else
	fq_codel
fi
}


tc qdisc del dev $IFACE root 2> /dev/null
fix_speed
fix_queues

exit 0