Browse Source

sqm-scripts: Smart Queue Management - experimental QoS

sqm-scripts is a new QoS system from Cerowrt / Bufferbloat.
I have tested it in my own community build.

More info at:
http://www.bufferbloat.net/projects/cerowrt/wiki/Smart_Queue_Management
http://www.bufferbloat.net/projects/cerowrt/wiki/Setting_up_SQM_for_CeroWrt_310

Dave Täht submitted this first via openwrt-devel mailing list in March 2014,
but that was not picked up before the switch to Github:
http://patchwork.openwrt.org/patch/5078/

Original code used as the base:
8ce2936110

I have modified:
- set the default interface to be eth1, like the Openwrt default.
- modified config to hide some of the advanced options by default
- beautified Makefile a bit
- added Toke Høiland-Jørgensen <toke@toke.dk> as the maintainer, as discussed
  in https://github.com/dtaht/ceropackages-3.10/issues/8#issuecomment-59215905

Signed-off-by: Hannu Nyman <hannu.nyman@iki.fi>
Hannu Nyman 10 years ago
parent
commit
5113575fb9

+ 50
- 0
net/sqm-scripts/Makefile View File

@@ -0,0 +1,50 @@
1
+# 
2
+# Copyright (C) 2014 OpenWrt.org
3
+#
4
+# This is free software, licensed under the GNU General Public License v2.
5
+# See /LICENSE for more information.
6
+#
7
+
8
+include $(TOPDIR)/rules.mk
9
+
10
+PKG_NAME:=sqm-scripts
11
+PKG_VERSION:=6
12
+PKG_RELEASE:=1
13
+
14
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
15
+
16
+include $(INCLUDE_DIR)/package.mk
17
+
18
+define Package/sqm-scripts
19
+  SECTION:=net
20
+  CATEGORY:=Base system
21
+  DEPENDS:=+tc +kmod-sched +kmod-ifb iptables +ip \
22
+	+iptables-mod-filter +iptables-mod-ipopt +iptables-mod-conntrack-extra
23
+  TITLE:=SQM Scripts (QoS)
24
+  PKGARCH:=all
25
+  MAINTAINER:=Toke Høiland-Jørgensen <toke@toke.dk>
26
+endef
27
+
28
+define Package/sqm-scripts/description
29
+ A set of scripts that does simple SQM configuration.
30
+endef
31
+
32
+define Package/sqm-scripts/conffiles
33
+/etc/config/sqm
34
+endef
35
+
36
+define Build/Prepare
37
+endef
38
+
39
+define Build/Configure
40
+endef
41
+
42
+define Build/Compile
43
+endef
44
+
45
+define Package/sqm-scripts/install
46
+	$(INSTALL_DIR) $(1)
47
+	$(CP) ./files/* $(1)/
48
+endef
49
+
50
+$(eval $(call BuildPackage,sqm-scripts))

+ 16
- 0
net/sqm-scripts/files/etc/config/sqm View File

@@ -0,0 +1,16 @@
1
+
2
+config queue 'eth1'
3
+        option enabled '0'
4
+        option interface 'eth1'
5
+        option download '85000'
6
+        option upload '10000'
7
+        option qdisc 'fq_codel'
8
+        option script 'simple.qos'
9
+        option qdisc_advanced '0'
10
+        option ingress_ecn 'ECN'
11
+        option egress_ecn 'NOECN'
12
+        option qdisc_really_really_advanced '0'
13
+        option itarget 'auto'
14
+        option etarget 'auto'
15
+        option linklayer 'none'
16
+

+ 23
- 0
net/sqm-scripts/files/etc/init.d/sqm View File

@@ -0,0 +1,23 @@
1
+#!/bin/sh /etc/rc.common
2
+
3
+START=50
4
+
5
+reload()
6
+{
7
+/usr/lib/sqm/run.sh
8
+}
9
+
10
+restart()
11
+{
12
+reload
13
+}
14
+
15
+start()
16
+{
17
+reload
18
+}
19
+
20
+stop()
21
+{
22
+/usr/lib/sqm/run.sh stop
23
+}

+ 493
- 0
net/sqm-scripts/files/usr/lib/sqm/functions.sh View File

@@ -0,0 +1,493 @@
1
+#improve the logread output
2
+sqm_logger() {
3
+    logger -t SQM -s ${1}
4
+}
5
+
6
+insmod() {
7
+  lsmod | grep -q ^$1 || $INSMOD $1
8
+}
9
+
10
+ipt() {
11
+  d=`echo $* | sed s/-A/-D/g`
12
+  [ "$d" != "$*" ] && {
13
+	iptables $d > /dev/null 2>&1
14
+	ip6tables $d > /dev/null 2>&1
15
+  }
16
+  d=`echo $* | sed s/-I/-D/g`
17
+  [ "$d" != "$*" ] && {
18
+	iptables $d > /dev/null 2>&1
19
+	ip6tables $d > /dev/null 2>&1
20
+  }
21
+  iptables $* > /dev/null 2>&1
22
+  ip6tables $* > /dev/null 2>&1
23
+}
24
+
25
+do_modules() {
26
+	insmod act_ipt
27
+	insmod sch_$QDISC
28
+	insmod sch_ingress
29
+	insmod act_mirred
30
+	insmod cls_fw
31
+	insmod sch_htb
32
+}
33
+
34
+
35
+# You need to jiggle these parameters. Note limits are tuned towards a <10Mbit uplink <60Mbup down
36
+
37
+[ -z "$UPLINK" ] && UPLINK=2302
38
+[ -z "$DOWNLINK" ] && DOWNLINK=14698
39
+[ -z "$IFACE" ] && IFACE=ge00
40
+[ -z "$QDISC" ] && QDISC=fq_codel
41
+[ -z "$LLAM" ] && LLAM="tc_stab"
42
+[ -z "$LINKLAYER" ] && LINKLAYER="none"
43
+[ -z "$OVERHEAD" ] && OVERHEAD=0
44
+[ -z "$STAB_MTU" ] && STAB_MTU=2047
45
+[ -z "$STAB_MPU" ] && STAB_MPU=0
46
+[ -z "$STAB_TSIZE" ] && STAB_TSIZE=512
47
+[ -z "$AUTOFLOW" ] && AUTOFLOW=0
48
+[ -z "$LIMIT" ] && LIMIT=1001	# sane global default for *LIMIT for fq_codel on a small memory device
49
+[ -z "$ILIMIT" ] && ILIMIT=
50
+[ -z "$ELIMIT" ] && ELIMIT=
51
+[ -z "$ITARGET" ] && ITARGET=
52
+[ -z "$ETARGET" ] && ETARGET=
53
+[ -z "$IECN" ] && IECN="ECN"
54
+[ -z "$EECN" ] && EECN="NOECN"
55
+[ -z "$SQUASH_DSCP" ] && SQUASH_DSCP="1"
56
+[ -z "SQUASH_INGRESS" ] && SQUASH_INGRESS="1"
57
+[ -z "$IQDISC_OPTS" ] && IQDISC_OPTS=""
58
+[ -z "$EQDISC_OPTS" ] && EQDISC_OPTS=""
59
+[ -z "$TC" ] && TC=`which tc`
60
+#[ -z "$TC" ] && TC="sqm_logger tc"# this redirects all tc calls into the log
61
+[ -z "$IP" ] && IP=$( which ip )
62
+[ -z "$INSMOD" ] && INSMOD=`which insmod`
63
+[ -z "TARGET" ] && TARGET="5ms"
64
+
65
+
66
+
67
+
68
+# find the ifb device associated with a specific interface, return nothing of no ifb is associated with IF
69
+get_ifb_associated_with_if() {
70
+    CUR_IF=$1
71
+    # CUR_IFB=$( tc -p filter show parent ffff: dev ${CUR_IF} | grep -o -e ifb'[[:digit:]]\+' )
72
+    CUR_IFB=$( tc -p filter show parent ffff: dev ${CUR_IF} | grep -o -e ifb'[^)]\+' )	# my editor's syntax coloration is limitied so I need a single quote in this line (between eiditor and s)
73
+    sqm_logger "ifb associated with interface ${CUR_IF}: ${CUR_IFB}"
74
+    echo ${CUR_IFB}
75
+}
76
+
77
+# what is the lowest-index currently not used ifb device
78
+#sm: hopefully this is not required any longer, and can be deleted after a bit more testing...
79
+get_lowest_unused_ifb() {
80
+    LOWEST_FREE_IFB=
81
+    # this just returns a list of currently existing IFBs, these need not be associated with any interface
82
+    CUR_UP_IFBS=$( ifconfig | grep -o -e ifb'[[:digit:]]\+' )
83
+    # the possible IFBs (N in insmod ifb numifbs=N)
84
+    here=$( pwd )
85
+    cd /sys/devices/virtual/net/
86
+    CUR_ALLOWED_IFBS=$( ls -d ifb* )
87
+    sqm_logger "Currently allowed IFBs: ${CUR_ALLOWED_IFBS}"
88
+    cd ${here}
89
+    # this is the sorted list of the active ifbs
90
+    # note for 3.10.32 unused and even down IFBs linger on in the tc output, so take $CUR_UP_IFBS instead
91
+    # a better test might be to check for each allowed IFB whether it is in use
92
+    # but the only way I figured out doing this means interating over all interfaces and that sounds costly
93
+    # so instead we rely on stop.sh actually calling ifconfig ${LAST_USED_IFB} down
94
+    CUR_USED_IFBS=$( tc -d qdisc | grep -o -e ifb'[[:digit:]]\+' | sort -u)
95
+    sqm_logger "Currently used IFBs: ${CUR_USED_IFBS}"
96
+    # now find the lowest index not in the sorted list
97
+    local CUR_IDX=0
98
+    while [ -z "$LOWEST_FREE_IFB" ]
99
+    do
100
+        #TMP=$( echo "${CUR_USED_IFBS}" | grep -o -e ifb${CUR_IDX} )
101
+        TMP=$( echo "${CUR_UP_IFBS}" | grep -o -e ifb${CUR_IDX} )
102
+        [ -z "$TMP" ] && LOWEST_FREE_IFB="ifb"${CUR_IDX}
103
+        CUR_IDX=$(( $CUR_IDX + 1 ))
104
+    done
105
+    # check whether the number is in the allowed range
106
+    LOWEST_FREE_IFB=$( echo "${CUR_ALLOWED_IFBS}" | grep -o -e ${LOWEST_FREE_IFB} )
107
+    [ -z "${LOWEST_FREE_IFB}" ] && sqm_logger "The IFB candidate ifb$(( ${CUR_IDX} - 1 )) is not in the range of allowed IFBs, bailing out..."
108
+    sqm_logger "selected ifb index: ${LOWEST_FREE_IFB}"
109
+    echo ${LOWEST_FREE_IFB}
110
+}
111
+
112
+# instead of playing around with indices just create a named IFB
113
+# ATTENTION, IFB names can only be 15 chararcters, so we chop of excessive characters at the start of the interface name 
114
+# if required
115
+create_new_ifb_for_if() {
116
+    CUR_IF=$1
117
+    MAX_IF_NAME_LENGTH=15
118
+    IFB_PREFIX="ifb4"
119
+    NEW_IFB="${IFB_PREFIX}${CUR_IF}"
120
+    IFB_NAME_LENGTH=${#NEW_IFB}
121
+    if [ ${IFB_NAME_LENGTH} -gt ${MAX_IF_NAME_LENGTH} ]; 
122
+    then
123
+	sqm_logger "The requsted IFB name ${NEW_IFB} is longer than the allowed 15 characters, trying to make it shorter"
124
+	OVERLIMIT=$(( ${#NEW_IFB} - ${MAX_IF_NAME_LENGTH} ))
125
+	NEW_IFB=${IFB_PREFIX}${CUR_IF:${OVERLIMIT}:$(( ${MAX_IF_NAME_LENGTH} - ${#IFB_PREFIX} ))}
126
+    fi
127
+    sqm_logger "trying to create new IFB: ${NEW_IFB}"
128
+    $IP link add name ${NEW_IFB} type ifb #>/dev/null 2>&1	# better be verbose
129
+    echo ${NEW_IFB}
130
+}
131
+
132
+# the best match is either the IFB already associated with the current interface or a new named IFB
133
+get_ifb_for_if() {
134
+    CUR_IF=$1
135
+    # if an ifb is already associated return that
136
+    CUR_IFB=$( get_ifb_associated_with_if ${CUR_IF} )
137
+    # otherwise find the lowest unused ifb device
138
+    #[ -z "$CUR_IFB" ] && CUR_IFB=$( get_lowest_unused_ifb )
139
+    [ -z "$CUR_IFB" ] && CUR_IFB=$( create_new_ifb_for_if ${CUR_IF} )
140
+    [ -z "$CUR_IFB" ] && sqm_logger "Could not find existing IFB for ${CUR_IF}, nor create a new IFB instead..."
141
+    echo ${CUR_IFB}
142
+}
143
+
144
+#sm: we need the functions above before trying to set the ingress IFB device
145
+[ -z "$DEV" ] && DEV=$( get_ifb_for_if ${IFACE} )      # automagically get the right IFB device for the IFACE"
146
+
147
+
148
+
149
+#sqm_logger "iqdisc opts: ${iqdisc_opts}"
150
+#sqm_logger "eqdisc opts: ${eqdisc_opts}"
151
+
152
+#sqm_logger "LLAM: ${LLAM}"
153
+#sqm_logger "LINKLAYER: ${LINKLAYER}"
154
+
155
+get_htb_adsll_string() {
156
+	ADSLL=""
157
+	if [ "$LLAM" = "htb_private" -a "$LINKLAYER" != "none" ]; 
158
+	then
159
+		# HTB defaults to MTU 1600 and an implicit fixed TSIZE of 256, but HTB as of around 3.10.0
160
+		# does not actually use a table in the kernel
161
+		ADSLL="mpu ${STAB_MPU} linklayer ${LINKLAYER} overhead ${OVERHEAD} mtu ${STAB_MTU}"
162
+		sqm_logger "ADSLL: ${ADSLL}"
163
+	fi
164
+	echo ${ADSLL}
165
+}
166
+
167
+get_stab_string() {
168
+	STABSTRING=""
169
+	if [ "${LLAM}" = "tc_stab" -a "$LINKLAYER" != "none" ]; 
170
+	then
171
+		STABSTRING="stab mtu ${STAB_MTU} tsize ${STAB_TSIZE} mpu ${STAB_MPU} overhead ${OVERHEAD} linklayer ${LINKLAYER}"
172
+		sqm_logger "STAB: ${STABSTRING}"
173
+	fi
174
+	echo ${STABSTRING}
175
+}
176
+
177
+sqm_stop() {
178
+	$TC qdisc del dev $IFACE ingress
179
+	$TC qdisc del dev $IFACE root
180
+	$TC qdisc del dev $DEV root
181
+}
182
+
183
+# Note this has side effects on the prio variable
184
+# and depends on the interface global too
185
+
186
+fc() {
187
+	$TC filter add dev $interface protocol ip parent $1 prio $prio u32 match ip tos $2 0xfc classid $3
188
+	prio=$(($prio + 1))
189
+	$TC filter add dev $interface protocol ipv6 parent $1 prio $prio u32 match ip6 priority $2 0xfc classid $3
190
+	prio=$(($prio + 1))
191
+}
192
+
193
+fc_pppoe() {
194
+	PPPOE_SESSION_ETHERTYPE="0x8864"
195
+	PPPOE_DISCOVERY_ETHERTYPE="0x8863"
196
+	PPP_PROTO_IP4="0x0021"
197
+	PPP_PROTO_IP6="0x0057"
198
+	ARP_PROTO_IP4="0x0806"
199
+	$TC filter add dev $interface protocol ip parent $1 prio $prio u32 match ip tos $2 0xfc classid $3
200
+	$TC filter add dev $interface parent $1 protocol ${PPPOE_SESSION_ETHERTYPE} prio $(( 400 + ${prio}  )) u32 \
201
+	    match u16 ${PPP_PROTO_IP4} 0xffff at 6 \
202
+	    match u8 $2 0xfc at 9 \
203
+	    flowid $3
204
+
205
+	prio=$(($prio + 1))
206
+	$TC filter add dev $interface protocol ipv6 parent $1 prio $prio u32 match ip6 priority $2 0xfc classid $3
207
+	$TC filter add dev $interface parent $1 protocol ${PPPOE_SESSION_ETHERTYPE} prio $(( 600 + ${prio} )) u32 \
208
+	    match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
209
+	    match u16 0x0${2:2:2}0 0x0fc0 at 8 \
210
+	    flowid $3
211
+	
212
+
213
+
214
+
215
+	prio=$(($prio + 1))
216
+
217
+
218
+}
219
+# FIXME: actually you need to get the underlying MTU on PPOE thing
220
+
221
+get_mtu() {
222
+	BW=$2
223
+	F=`cat /sys/class/net/$1/mtu`
224
+	if [ -z "$F" ]
225
+	then
226
+	F=1500
227
+	fi
228
+	if [ $BW -gt 20000 ]
229
+	then
230
+		F=$(($F * 2))
231
+	fi
232
+	if [ $BW -gt 30000 ]
233
+	then
234
+		F=$(($F * 2))
235
+	fi
236
+	if [ $BW -gt 40000 ]
237
+	then
238
+		F=$(($F * 2))
239
+	fi
240
+	if [ $BW -gt 50000 ]
241
+	then
242
+		F=$(($F * 2))
243
+	fi
244
+	if [ $BW -gt 60000 ]
245
+	then
246
+		F=$(($F * 2))
247
+	fi
248
+	if [ $BW -gt 80000 ]
249
+	then
250
+		F=$(($F * 2))
251
+	fi
252
+	echo $F
253
+}
254
+
255
+# FIXME should also calculate the limit
256
+# Frankly I think Xfq_codel can pretty much always run with high numbers of flows
257
+# now that it does fate sharing
258
+# But right now I'm trying to match the ns2 model behavior better
259
+# So SET the autoflow variable to 1 if you want the cablelabs behavior
260
+
261
+get_flows() {
262
+	if [ "$AUTOFLOW" -eq "1" ] 
263
+	then
264
+		FLOWS=8
265
+		[ $1 -gt 999 ] && FLOWS=16
266
+		[ $1 -gt 2999 ] && FLOWS=32
267
+		[ $1 -gt 7999 ] && FLOWS=48
268
+		[ $1 -gt 9999 ] && FLOWS=64
269
+		[ $1 -gt 19999 ] && FLOWS=128
270
+		[ $1 -gt 39999 ] && FLOWS=256
271
+		[ $1 -gt 69999 ] && FLOWS=512
272
+		[ $1 -gt 99999 ] && FLOWS=1024
273
+		case $QDISC in
274
+			codel|ns2_codel|pie|*fifo|pfifo_fast) ;;
275
+			fq_codel|*fq_codel|sfq) echo flows $FLOWS ;;
276
+		esac
277
+	fi
278
+}	
279
+
280
+# set the target parameter, also try to only take well formed inputs
281
+# Note, the link bandwidth in the current direction (ingress or egress) 
282
+# is required to adjust the target for slow links
283
+get_target() {
284
+	local CUR_TARGET=${1}
285
+	local CUR_LINK_KBPS=${2}
286
+	[ ! -z "$CUR_TARGET" ] && sqm_logger "cur_target: ${CUR_TARGET} cur_bandwidth: ${CUR_LINK_KBPS}"
287
+	CUR_TARGET_STRING=
288
+	# either e.g. 100ms or auto
289
+	CUR_TARGET_VALUE=$( echo ${CUR_TARGET} | grep -o -e \^'[[:digit:]]\+' )
290
+	CUR_TARGET_UNIT=$( echo ${CUR_TARGET} | grep -o -e '[[:alpha:]]\+'\$ )
291
+#	[ ! -z "$CUR_TARGET" ] && sqm_logger "CUR_TARGET_VALUE: $CUR_TARGET_VALUE"
292
+#	[ ! -z "$CUR_TARGET" ] && sqm_logger "CUR_TARGET_UNIT: $CUR_TARGET_UNIT"
293
+	
294
+	AUTO_TARGET=
295
+	UNIT_VALID=
296
+	
297
+	case $QDISC in
298
+		*codel|*pie) 
299
+			if [ ! -z "${CUR_TARGET_VALUE}" -a ! -z "${CUR_TARGET_UNIT}" ];
300
+    			then
301
+    			    case ${CUR_TARGET_UNIT} in
302
+    				    # permissible units taken from: tc_util.c get_time()
303
+				    s|sec|secs|ms|msec|msecs|us|usec|usecs) 
304
+					CUR_TARGET_STRING="target ${CUR_TARGET_VALUE}${CUR_TARGET_UNIT}" 
305
+					UNIT_VALID="1"
306
+					;;
307
+			    esac
308
+			fi
309
+			case ${CUR_TARGET_UNIT} in
310
+			    auto|Auto|AUTO) 
311
+				if [ ! -z "${CUR_LINK_KBPS}" ];
312
+				then
313
+				    TMP_TARGET_US=$( adapt_target_to_slow_link $CUR_LINK_KBPS )
314
+				    TMP_INTERVAL_STRING=$( adapt_interval_to_slow_link $TMP_TARGET_US )
315
+				    CUR_TARGET_STRING="target ${TMP_TARGET_US}us ${TMP_INTERVAL_STRING}"
316
+				    AUTO_TARGET="1"
317
+			    	else
318
+			    	    sqm_logger "required link bandwidth in kbps not passed to get_target()." 
319
+			        fi
320
+			    ;;
321
+			esac
322
+			if [ ! -z "${CUR_TARGET}" ];
323
+			    then
324
+			    if [ -z "${CUR_TARGET_VALUE}" -o -z "${UNIT_VALID}" ];
325
+			    then 
326
+				[ -z "$AUTO_TARGET" ] && sqm_logger "${CUR_TARGET} is not a well formed tc target specifier; e.g.: 5ms (or s, us), or the string auto."
327
+			    fi
328
+			fi
329
+		    ;;
330
+	esac
331
+#	sqm_logger "target: ${CUR_TARGET_STRING}"
332
+	echo $CUR_TARGET_STRING
333
+}	
334
+
335
+# for low bandwidth links fq_codels default target of 5ms does not work too well
336
+# so increase target for slow links (note below roughly 2500kbps a single packet will \
337
+# take more than 5 ms to be tansfered over the wire)
338
+adapt_target_to_slow_link() {
339
+    CUR_LINK_KBPS=$1
340
+    CUR_EXTENDED_TARGET_US=
341
+    MAX_PAKET_DELAY_IN_US_AT_1KBPS=$(( 1000 * 1000 *1540 * 8 / 1000 ))
342
+    CUR_EXTENDED_TARGET_US=$(( ${MAX_PAKET_DELAY_IN_US_AT_1KBPS} / ${CUR_LINK_KBPS} ))	# note this truncates the decimals
343
+    # do not change anything for fast links
344
+    [ "$CUR_EXTENDED_TARGET_US" -lt 5000 ] && CUR_EXTENDED_TARGET_US=5000
345
+    case ${QDISC} in
346
+        *codel|pie)
347
+	    echo "${CUR_EXTENDED_TARGET_US}"
348
+	    ;;
349
+    esac
350
+}
351
+
352
+# codel looks at a whole interval to figure out wether observed latency stayed below target
353
+# if target >= interval that will not work well, so increase interval by the same amonut that target got increased
354
+adapt_interval_to_slow_link() {
355
+    CUR_TARGET_US=$1
356
+    case ${QDISC} in
357
+        *codel)
358
+            CUR_EXTENDED_INTERVAL_US=$(( (100 - 5) * 1000 + ${CUR_TARGET_US} ))
359
+	    echo "interval ${CUR_EXTENDED_INTERVAL_US}us"
360
+	    ;;
361
+	pie)
362
+	    ## not sure if pie needs this, probably not
363
+	    #CUR_EXTENDED_TUPDATE_US=$(( (30 - 20) * 1000 + ${CUR_TARGET_US} ))
364
+	    #echo "tupdate ${CUR_EXTENDED_TUPDATE_US}us"
365
+	    ;;
366
+    esac
367
+}
368
+
369
+
370
+# set quantum parameter if available for this qdisc
371
+get_quantum() {
372
+    case $QDISC in
373
+	*fq_codel|fq_pie|drr) echo quantum $1 ;;
374
+	*) ;;
375
+    esac
376
+}
377
+
378
+# only show limits to qdiscs that can handle them...
379
+# Note that $LIMIT contains the default limit
380
+get_limit() {
381
+    CURLIMIT=$1
382
+    case $QDISC in
383
+    *codel|*pie|pfifo_fast|sfq|pfifo) [ -z ${CURLIMIT} ] && CURLIMIT=${LIMIT}	# use the global default limit
384
+        ;;
385
+    bfifo) [ -z "$CURLIMIT" ] && [ ! -z "$LIMIT" ] && CURLIMIT=$(( ${LIMIT} * $( cat /sys/class/net/${IFACE}/mtu ) ))	# bfifo defaults to txquelength * MTU, 
386
+        ;;
387
+    *) sqm_logger "${QDISC} does not support a limit"
388
+        ;;
389
+    esac
390
+    sqm_logger "get_limit: $1 CURLIMIT: ${CURLIMIT}"
391
+    
392
+    if [ ! -z "$CURLIMIT" ]
393
+    then
394
+    echo "limit ${CURLIMIT}"
395
+    fi
396
+}
397
+
398
+get_ecn() {
399
+    CURECN=$1
400
+    #sqm_logger CURECN: $CURECN
401
+	case ${CURECN} in
402
+		ECN)
403
+			case $QDISC in
404
+				*codel|*pie|*red)
405
+				    CURECN=ecn 
406
+				    ;;
407
+				*) 
408
+				    CURECN="" 
409
+				    ;;
410
+			esac
411
+			;;
412
+		NOECN)
413
+			case $QDISC in
414
+				*codel|*pie|*red) 
415
+				    CURECN=noecn 
416
+				    ;;
417
+				*) 
418
+				    CURECN="" 
419
+				    ;;
420
+			esac
421
+			;;
422
+		*)
423
+		    sqm_logger "ecn value $1 not handled"
424
+		    ;;
425
+	esac
426
+	#sqm_logger "get_ECN: $1 CURECN: ${CURECN} IECN: ${IECN} EECN: ${EECN}"
427
+	echo ${CURECN}
428
+
429
+}
430
+
431
+# This could be a complete diffserv implementation
432
+
433
+diffserv() {
434
+
435
+interface=$1
436
+prio=1
437
+
438
+# Catchall
439
+
440
+$TC filter add dev $interface parent 1:0 protocol all prio 999 u32 \
441
+        match ip protocol 0 0x00 flowid 1:12
442
+
443
+# Find the most common matches fast
444
+#fc_pppoe() instead of fc() with effectice ingress classification for pppoe is very expensive and destroys LUL
445
+
446
+fc 1:0 0x00 1:12 # BE
447
+fc 1:0 0x20 1:13 # CS1
448
+fc 1:0 0x10 1:11 # IMM
449
+fc 1:0 0xb8 1:11 # EF
450
+fc 1:0 0xc0 1:11 # CS3
451
+fc 1:0 0xe0 1:11 # CS6
452
+fc 1:0 0x90 1:11 # AF42 (mosh)
453
+
454
+# Arp traffic
455
+$TC filter add dev $interface protocol arp parent 1:0 prio $prio handle 500 fw flowid 1:11
456
+
457
+
458
+prio=$(($prio + 1))
459
+
460
+
461
+}
462
+
463
+diffserv_pppoe() {
464
+
465
+interface=$1
466
+prio=1
467
+
468
+# Catchall
469
+
470
+$TC filter add dev $interface parent 1:0 protocol all prio 999 u32 \
471
+        match ip protocol 0 0x00 flowid 1:12
472
+
473
+# Find the most common matches fast
474
+#fc_pppoe() instead of fc() with effectice ingress classification for pppoe is very expensive and destroys LUL
475
+
476
+fc_pppoe 1:0 0x00 1:12 # BE
477
+fc_pppoe 1:0 0x20 1:13 # CS1
478
+fc_pppoe 1:0 0x10 1:11 # IMM
479
+fc_pppoe 1:0 0xb8 1:11 # EF
480
+fc_pppoe 1:0 0xc0 1:11 # CS3
481
+fc_pppoe 1:0 0xe0 1:11 # CS6
482
+fc_pppoe 1:0 0x90 1:11 # AF42 (mosh)
483
+
484
+# Arp traffic
485
+$TC filter add dev $interface protocol arp parent 1:0 prio $prio handle 500 fw flowid 1:11
486
+
487
+
488
+prio=$(($prio + 1))
489
+
490
+
491
+}
492
+
493
+

+ 82
- 0
net/sqm-scripts/files/usr/lib/sqm/run.sh View File

@@ -0,0 +1,82 @@
1
+#!/bin/sh
2
+
3
+. /lib/functions.sh
4
+
5
+STOP=$1
6
+ACTIVE_STATE_PREFIX="SQM_active_on_"
7
+ACTIVE_STATE_FILE_DIR="/var/run/SQM"
8
+mkdir -p ${ACTIVE_STATE_FILE_DIR}
9
+
10
+# the current uci config file does not necessarily contain sections for all interfaces with active
11
+# SQM instances, so use the ACTIVE_STATE_FILES to detect the interfaces on which to stop SQM.
12
+# Currently the .qos scripts start with stopping any existing traffic shaping so this should not
13
+# effectively change anything...
14
+PROTO_STATE_FILE_LIST=$( ls ${ACTIVE_STATE_FILE_DIR}/${ACTIVE_STATE_PREFIX}* 2> /dev/null )
15
+for STATE_FILE in ${PROTO_STATE_FILE_LIST} ; do
16
+    if [ -f ${STATE_FILE} ] ;
17
+    then
18
+	STATE_FILE_BASE_NAME=$( basename ${STATE_FILE} )
19
+	CURRENT_INTERFACE=${STATE_FILE_BASE_NAME:${#ACTIVE_STATE_PREFIX}:$(( ${#STATE_FILE_BASE_NAME} - ${#ACTIVE_STATE_PREFIX} ))}        
20
+	logger -t SQM -s "Stopping SQM on interface: ${CURRENT_INTERFACE}"
21
+	/usr/lib/sqm/stop.sh ${CURRENT_INTERFACE}
22
+	rm ${STATE_FILE}	# well, we stop it so it is not running anymore and hence no active state file needed...
23
+    fi
24
+done
25
+
26
+config_load sqm
27
+
28
+run_simple_qos() {
29
+	local section="$1"
30
+	export IFACE=$(config_get "$section" interface)
31
+	ACTIVE_STATE_FILE_FQN="${ACTIVE_STATE_FILE_DIR}/${ACTIVE_STATE_PREFIX}${IFACE}"	# this marks interfaces as active with SQM
32
+	[ -f "${ACTIVE_STATE_FILE_FQN}" ] && logger -t SQM -s "Uh, oh, ${ACTIVE_STATE_FILE_FQN} should already be stopped."	# Not supposed to happen
33
+
34
+	if [ $(config_get "$section" enabled) -ne 1 ];
35
+	then
36
+	    if [ -f "${ACTIVE_STATE_FILE_FQN}" ];
37
+	    then
38
+		# this should not be possible, delete after testing
39
+		local SECTION_STOP="stop"	# it seems the user just de-selected enable, so stop the active SQM
40
+	    else
41
+		logger -t SQM -s "SQM for interface ${IFACE} is not enabled, skipping over..."
42
+		return 0	# since SQM is not active on the current interface nothing to do here
43
+	    fi
44
+	fi
45
+
46
+	export UPLINK=$(config_get "$section" upload)
47
+	export DOWNLINK=$(config_get "$section" download)
48
+	export LLAM=$(config_get "$section" linklayer_adaptation_mechanism)
49
+	export LINKLAYER=$(config_get "$section" linklayer)
50
+	export OVERHEAD=$(config_get "$section" overhead)
51
+	export STAB_MTU=$(config_get "$section" tcMTU)
52
+	export STAB_TSIZE=$(config_get "$section" tcTSIZE)
53
+	export STAB_MPU=$(config_get "$section" tcMPU)
54
+	export ILIMIT=$(config_get "$section" ilimit)
55
+	export ELIMIT=$(config_get "$section" elimit)
56
+	export ITARGET=$(config_get "$section" itarget)
57
+	export ETARGET=$(config_get "$section" etarget)
58
+	export IECN=$(config_get "$section" ingress_ecn)
59
+	export EECN=$(config_get "$section" egress_ecn)
60
+	export IQDISC_OPTS=$(config_get "$section" iqdisc_opts)
61
+	export EQDISC_OPTS=$(config_get "$section" eqdisc_opts)
62
+	export TARGET=$(config_get "$section" target)
63
+	export SQUASH_DSCP=$(config_get "$section" squash_dscp)
64
+	export SQUASH_INGRESS=$(config_get "$section" squash_ingress)
65
+
66
+	export QDISC=$(config_get "$section" qdisc)
67
+	export SCRIPT=/usr/lib/sqm/$(config_get "$section" script)
68
+
69
+#	# there should be nothing left to stop, so just avoid calling the script
70
+	if [ "$STOP" == "stop" -o "$SECTION_STOP" == "stop" ];
71
+	then 
72
+#	     /usr/lib/sqm/stop.sh
73
+#	     [ -f ${ACTIVE_STATE_FILE_FQN} ] && rm ${ACTIVE_STATE_FILE_FQN}	# conditional to avoid errors ACTIVE_STATE_FILE_FQN does not exist anymore
74
+#	     $(config_set "$section" enabled 0)	# this does not save to the config file only to the loaded memory representation
75
+#	     logger -t SQM -s "SQM qdiscs on ${IFACE} removed"
76
+	     return 0
77
+	fi
78
+	logger -t SQM -s "Queue Setup Script: ${SCRIPT}"
79
+	[ -x "$SCRIPT" ] && { $SCRIPT ; touch ${ACTIVE_STATE_FILE_FQN}; }
80
+}
81
+
82
+config_foreach run_simple_qos

+ 212
- 0
net/sqm-scripts/files/usr/lib/sqm/simple.qos View File

@@ -0,0 +1,212 @@
1
+#!/bin/sh
2
+# Cero3 Shaper
3
+# A 3 bin tc_codel and ipv6 enabled shaping script for
4
+# ethernet gateways
5
+
6
+# Copyright (C) 2012 Michael D Taht
7
+# GPLv2
8
+
9
+# Compared to the complexity that debloat had become
10
+# this cleanly shows a means of going from diffserv marking
11
+# to prioritization using the current tools (ip(6)tables
12
+# and tc. I note that the complexity of debloat exists for
13
+# a reason, and it is expected that script is run first
14
+# to setup various other parameters such as BQL and ethtool.
15
+# (And that the debloat script has setup the other interfaces)
16
+
17
+# You need to jiggle these parameters. Note limits are tuned towards a <10Mbit uplink <60Mbup down
18
+
19
+. /usr/lib/sqm/functions.sh
20
+
21
+ipt_setup() {
22
+
23
+ipt -t mangle -N QOS_MARK_${IFACE}
24
+
25
+ipt -t mangle -A QOS_MARK_${IFACE} -j MARK --set-mark 0x2
26
+# You can go further with classification but...
27
+ipt -t mangle -A QOS_MARK_${IFACE} -m dscp --dscp-class CS1 -j MARK --set-mark 0x3
28
+ipt -t mangle -A QOS_MARK_${IFACE} -m dscp --dscp-class CS6 -j MARK --set-mark 0x1
29
+ipt -t mangle -A QOS_MARK_${IFACE} -m dscp --dscp-class EF -j MARK --set-mark 0x1
30
+ipt -t mangle -A QOS_MARK_${IFACE} -m dscp --dscp-class AF42 -j MARK --set-mark 0x1
31
+ipt -t mangle -A QOS_MARK_${IFACE} -m tos  --tos Minimize-Delay -j MARK --set-mark 0x1
32
+
33
+# and it might be a good idea to do it for udp tunnels too
34
+
35
+# Turn it on. Preserve classification if already performed
36
+
37
+if [ "$SQUASH_DSCP" = "1" ]
38
+then
39
+sqm_logger "Squashing differentiad services code points (DSCP) from ingress."
40
+ipt -t mangle -I PREROUTING -i $IFACE -m dscp ! --dscp 0 -j DSCP --set-dscp-class be
41
+else
42
+sqm_logger "Keeping differentiad services code points (DSCP) from ingress."
43
+ipt -t mangle -A PREROUTING -i $IFACE -m mark --mark 0x00 -g QOS_MARK_${IFACE} 
44
+fi
45
+
46
+ipt -t mangle -A POSTROUTING -o $IFACE -m mark --mark 0x00 -g QOS_MARK_${IFACE} 
47
+
48
+# The Syn optimization was nice but fq_codel does it for us
49
+# ipt -t mangle -A PREROUTING -i s+ -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -j MARK --set-mark 0x01
50
+# Not sure if this will work. Encapsulation is a problem period
51
+
52
+ipt -t mangle -I PREROUTING -i vtun+ -p tcp -j MARK --set-mark 0x2 # tcp tunnels need ordering
53
+
54
+# Emanating from router, do a little more optimization
55
+# but don't bother with it too much. 
56
+
57
+ipt -t mangle -A OUTPUT -p udp -m multiport --ports 123,53 -j DSCP --set-dscp-class AF42
58
+
59
+#Not clear if the second line is needed
60
+#ipt -t mangle -A OUTPUT -o $IFACE -g QOS_MARK_${IFACE}
61
+
62
+}
63
+
64
+
65
+# TC rules
66
+
67
+egress() {
68
+
69
+CEIL=${UPLINK}
70
+PRIO_RATE=`expr $CEIL / 3` # Ceiling for prioirty
71
+BE_RATE=`expr $CEIL / 6`   # Min for best effort
72
+BK_RATE=`expr $CEIL / 6`   # Min for background
73
+BE_CEIL=`expr $CEIL - 16`  # A little slop at the top
74
+
75
+LQ="quantum `get_mtu $IFACE $CEIL`"
76
+
77
+$TC qdisc del dev $IFACE root 2> /dev/null
78
+$TC qdisc add dev $IFACE root handle 1: `get_stab_string` htb default 12
79
+$TC class add dev $IFACE parent 1: classid 1:1 htb $LQ rate ${CEIL}kbit ceil ${CEIL}kbit `get_htb_adsll_string`
80
+$TC class add dev $IFACE parent 1:1 classid 1:10 htb $LQ rate ${CEIL}kbit ceil ${CEIL}kbit prio 0 `get_htb_adsll_string`
81
+$TC class add dev $IFACE parent 1:1 classid 1:11 htb $LQ rate 128kbit ceil ${PRIO_RATE}kbit prio 1 `get_htb_adsll_string`
82
+$TC class add dev $IFACE parent 1:1 classid 1:12 htb $LQ rate ${BE_RATE}kbit ceil ${BE_CEIL}kbit prio 2 `get_htb_adsll_string`
83
+$TC class add dev $IFACE parent 1:1 classid 1:13 htb $LQ rate ${BK_RATE}kbit ceil ${BE_CEIL}kbit prio 3 `get_htb_adsll_string`
84
+
85
+$TC qdisc add dev $IFACE parent 1:11 handle 110: $QDISC `get_limit ${ELIMIT}` `get_target "${ETARGET}" ${UPLINK}` `get_ecn ${EECN}` `get_quantum 300` `get_flows ${PRIO_RATE}` ${EQDISC_OPTS}
86
+$TC qdisc add dev $IFACE parent 1:12 handle 120: $QDISC `get_limit ${ELIMIT}` `get_target "${ETARGET}" ${UPLINK}` `get_ecn ${EECN}` `get_quantum 300` `get_flows ${BE_RATE}` ${EQDISC_OPTS}
87
+$TC qdisc add dev $IFACE parent 1:13 handle 130: $QDISC `get_limit ${ELIMIT}` `get_target "${ETARGET}" ${UPLINK}` `get_ecn ${EECN}` `get_quantum 300` `get_flows ${BK_RATE}` ${EQDISC_OPTS}
88
+
89
+
90
+# Need a catchall rule
91
+
92
+$TC filter add dev $IFACE parent 1:0 protocol all prio 999 u32 \
93
+        match ip protocol 0 0x00 flowid 1:12  
94
+
95
+# FIXME should probably change the filter here to do pre-nat
96
+        
97
+$TC filter add dev $IFACE parent 1:0 protocol ip prio 1 handle 1 fw classid 1:11
98
+$TC filter add dev $IFACE parent 1:0 protocol ip prio 2 handle 2 fw classid 1:12
99
+$TC filter add dev $IFACE parent 1:0 protocol ip prio 3 handle 3 fw classid 1:13
100
+
101
+# ipv6 support. Note that the handle indicates the fw mark bucket that is looked for
102
+
103
+$TC filter add dev $IFACE parent 1:0 protocol ipv6 prio 4 handle 1 fw classid 1:11
104
+$TC filter add dev $IFACE parent 1:0 protocol ipv6 prio 5 handle 2 fw classid 1:12
105
+$TC filter add dev $IFACE parent 1:0 protocol ipv6 prio 6 handle 3 fw classid 1:13
106
+
107
+# Arp traffic
108
+
109
+$TC filter add dev $IFACE parent 1:0 protocol arp prio 7 handle 1 fw classid 1:11
110
+
111
+# ICMP traffic - Don't impress your friends. Deoptimize to manage ping floods
112
+# better instead
113
+
114
+$TC filter add dev $IFACE parent 1:0 protocol ip prio 8 \
115
+	 u32 match ip protocol 1 0xff flowid 1:13
116
+
117
+$TC filter add dev $IFACE parent 1:0 protocol ipv6 prio 9 \
118
+	 u32 match ip protocol 1 0xff flowid 1:13
119
+
120
+#diffserv $IFACE
121
+
122
+}
123
+
124
+ingress() {
125
+
126
+CEIL=$DOWNLINK
127
+PRIO_RATE=`expr $CEIL / 3` # Ceiling for prioirty
128
+BE_RATE=`expr $CEIL / 6`   # Min for best effort
129
+BK_RATE=`expr $CEIL / 6`   # Min for background
130
+BE_CEIL=`expr $CEIL - 16`  # A little slop at the top
131
+
132
+LQ="quantum `get_mtu $IFACE $CEIL`"
133
+
134
+$TC qdisc del dev $IFACE handle ffff: ingress 2> /dev/null
135
+$TC qdisc add dev $IFACE handle ffff: ingress
136
+
137
+$TC qdisc del dev $DEV root  2> /dev/null
138
+
139
+if [ "$SQUASH_INGRESS" = "1" ]
140
+then
141
+sqm_logger "Do not perform DSCP based filtering on ingress. (1-tier classification)"
142
+# Revert to no dscp based filtering
143
+$TC qdisc del dev $DEV root 2>/dev/null
144
+$TC qdisc add dev $DEV root handle 1: `get_stab_string` htb default 10
145
+$TC class add dev $DEV parent 1: classid 1:1 htb $LQ rate ${DOWNLINK}kbit ceil ${DOWNLINK}kbit `get_htb_adsll_string`
146
+$TC class add dev $DEV parent 1:1 classid 1:10 htb $LQ rate ${DOWNLINK}kbit ceil ${DOWNLINK}kbit prio 0 `get_htb_adsll_string`
147
+$TC qdisc add dev $DEV parent 1:10 handle 110: $QDISC `get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_flows ${DOWNLINK}` ${IQDISC_OPTS}
148
+
149
+else
150
+sqm_logger "Perform DSCP based filtering on ingress. (3-tier classification)"
151
+$TC qdisc add dev $DEV root handle 1: `get_stab_string` htb default 12
152
+$TC class add dev $DEV parent 1: classid 1:1 htb $LQ rate ${CEIL}kbit ceil ${CEIL}kbit `get_htb_adsll_string`
153
+$TC class add dev $DEV parent 1:1 classid 1:10 htb $LQ rate ${CEIL}kbit ceil ${CEIL}kbit prio 0 `get_htb_adsll_string`
154
+$TC class add dev $DEV parent 1:1 classid 1:11 htb $LQ rate 32kbit ceil ${PRIO_RATE}kbit prio 1 `get_htb_adsll_string`
155
+$TC class add dev $DEV parent 1:1 classid 1:12 htb $LQ rate ${BE_RATE}kbit ceil ${BE_CEIL}kbit prio 2 `get_htb_adsll_string`
156
+$TC class add dev $DEV parent 1:1 classid 1:13 htb $LQ rate ${BK_RATE}kbit ceil ${BE_CEIL}kbit prio 3 `get_htb_adsll_string`
157
+
158
+# I'd prefer to use a pre-nat filter but that causes permutation...
159
+
160
+$TC qdisc add dev $DEV parent 1:11 handle 110: $QDISC `get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_quantum 500` `get_flows ${PRIO_RATE}` ${IQDISC_OPTS}
161
+$TC qdisc add dev $DEV parent 1:12 handle 120: $QDISC `get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_quantum 1500` `get_flows ${BE_RATE}` ${IQDISC_OPTS}
162
+$TC qdisc add dev $DEV parent 1:13 handle 130: $QDISC `get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_quantum 300` `get_flows ${BK_RATE}` ${IQDISC_OPTS}
163
+
164
+diffserv $DEV
165
+
166
+fi
167
+
168
+ifconfig $DEV up
169
+
170
+# redirect all IP packets arriving in $IFACE to ifb0 
171
+
172
+$TC filter add dev $IFACE parent ffff: protocol all prio 10 u32 \
173
+  match u32 0 0 flowid 1:1 action mirred egress redirect dev $DEV
174
+
175
+}
176
+
177
+do_modules
178
+ipt_setup
179
+
180
+if [ "$UPLINK" -ne 0 ];
181
+then
182
+	egress
183
+	sqm_logger "egress shaping activated"
184
+else
185
+	sqm_logger "egress shaping deactivated"
186
+	tc qdisc del dev $IFACE root 2> /dev/null
187
+fi
188
+if [ "$DOWNLINK" -ne 0 ];
189
+then
190
+	ingress
191
+	sqm_logger "ingress shaping activated"
192
+else
193
+	sqm_logger "ingress shaping deactivated"
194
+	tc qdisc del dev $DEV root 2> /dev/null
195
+	tc qdisc del dev $IFACE ingress 2> /dev/null
196
+fi
197
+
198
+
199
+
200
+# References:
201
+# This alternate shaper attempts to go for 1/u performance in a clever way
202
+# http://git.coverfire.com/?p=linux-qos-scripts.git;a=blob;f=src-3tos.sh;hb=HEAD
203
+
204
+# Comments
205
+# This does the right thing with ipv6 traffic.
206
+# It also tries to leverage diffserv to some sane extent. In particular,
207
+# the 'priority' queue is limited to 33% of the total, so EF, and IMM traffic
208
+# cannot starve other types. The rfc suggested 30%. 30% is probably
209
+# a lot in today's world.
210
+
211
+# Flaws
212
+# Many!

+ 1
- 0
net/sqm-scripts/files/usr/lib/sqm/simple.qos.help View File

@@ -0,0 +1 @@
1
+BW-limited three-tier prioritisation scheme with fq_codel on each queue. (default)

+ 387
- 0
net/sqm-scripts/files/usr/lib/sqm/simple_pppoe.qos View File

@@ -0,0 +1,387 @@
1
+#!/bin/sh
2
+# Cero3 Shaper
3
+# A 3 bin tc_codel and ipv6 enabled shaping script for
4
+# ethernet gateways
5
+
6
+# Copyright (C) 2012 Michael D Taht
7
+# GPLv2
8
+
9
+# Compared to the complexity that debloat had become
10
+# this cleanly shows a means of going from diffserv marking
11
+# to prioritization using the current tools (ip(6)tables
12
+# and tc. I note that the complexity of debloat exists for
13
+# a reason, and it is expected that script is run first
14
+# to setup various other parameters such as BQL and ethtool.
15
+# (And that the debloat script has setup the other interfaces)
16
+
17
+# You need to jiggle these parameters. Note limits are tuned towards a <10Mbit uplink <60Mbup down
18
+
19
+. /usr/lib/sqm/functions.sh
20
+
21
+ipt_setup() {
22
+
23
+ipt -t mangle -N QOS_MARK_${IFACE}
24
+
25
+ipt -t mangle -A QOS_MARK_${IFACE} -j MARK --set-mark 0x2
26
+# You can go further with classification but...
27
+ipt -t mangle -A QOS_MARK_${IFACE} -m dscp --dscp-class CS1 -j MARK --set-mark 0x3
28
+ipt -t mangle -A QOS_MARK_${IFACE} -m dscp --dscp-class CS6 -j MARK --set-mark 0x1
29
+ipt -t mangle -A QOS_MARK_${IFACE} -m dscp --dscp-class EF -j MARK --set-mark 0x1
30
+ipt -t mangle -A QOS_MARK_${IFACE} -m dscp --dscp-class AF42 -j MARK --set-mark 0x1
31
+ipt -t mangle -A QOS_MARK_${IFACE} -m tos  --tos Minimize-Delay -j MARK --set-mark 0x1
32
+
33
+# and it might be a good idea to do it for udp tunnels too
34
+
35
+# Turn it on. Preserve classification if already performed
36
+
37
+if [ "$SQUASH_DSCP" = "1" ]
38
+then
39
+sqm_logger "Squashing differentiad services code points (DSCP) from ingress."
40
+ipt -t mangle -I PREROUTING -i $IFACE -m dscp ! --dscp 0 -j DSCP --set-dscp-class be
41
+else
42
+sqm_logger "Keeping differentiad services code points (DSCP) from ingress."
43
+ipt -t mangle -A PREROUTING -i $IFACE -m mark --mark 0x00 -g QOS_MARK_${IFACE} 
44
+fi
45
+
46
+ipt -t mangle -A POSTROUTING -o $IFACE -m mark --mark 0x00 -g QOS_MARK_${IFACE} 
47
+
48
+# The Syn optimization was nice but fq_codel does it for us
49
+# ipt -t mangle -A PREROUTING -i s+ -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -j MARK --set-mark 0x01
50
+# Not sure if this will work. Encapsulation is a problem period
51
+
52
+ipt -t mangle -I PREROUTING -i vtun+ -p tcp -j MARK --set-mark 0x2 # tcp tunnels need ordering
53
+
54
+# Emanating from router, do a little more optimization
55
+# but don't bother with it too much. 
56
+
57
+ipt -t mangle -A OUTPUT -p udp -m multiport --ports 123,53 -j DSCP --set-dscp-class AF42
58
+
59
+#Not clear if the second line is needed
60
+#ipt -t mangle -A OUTPUT -o $IFACE -g QOS_MARK_${IFACE}
61
+
62
+}
63
+
64
+
65
+# TC rules
66
+
67
+egress() {
68
+
69
+CEIL=${UPLINK}
70
+PRIO_RATE=`expr $CEIL / 3` # Ceiling for prioirty
71
+BE_RATE=`expr $CEIL / 6`   # Min for best effort
72
+BK_RATE=`expr $CEIL / 6`   # Min for background
73
+BE_CEIL=`expr $CEIL - 16`  # A little slop at the top
74
+
75
+LQ="quantum `get_mtu $IFACE $CEIL`"
76
+
77
+$TC qdisc del dev $IFACE root 2> /dev/null
78
+$TC qdisc add dev $IFACE root handle 1: `get_stab_string` htb default 12
79
+$TC class add dev $IFACE parent 1: classid 1:1 htb $LQ rate ${CEIL}kbit ceil ${CEIL}kbit `get_htb_adsll_string`
80
+$TC class add dev $IFACE parent 1:1 classid 1:10 htb $LQ rate ${CEIL}kbit ceil ${CEIL}kbit prio 0 `get_htb_adsll_string`
81
+$TC class add dev $IFACE parent 1:1 classid 1:11 htb $LQ rate 128kbit ceil ${PRIO_RATE}kbit prio 1 `get_htb_adsll_string`
82
+$TC class add dev $IFACE parent 1:1 classid 1:12 htb $LQ rate ${BE_RATE}kbit ceil ${BE_CEIL}kbit prio 2 `get_htb_adsll_string`
83
+$TC class add dev $IFACE parent 1:1 classid 1:13 htb $LQ rate ${BK_RATE}kbit ceil ${BE_CEIL}kbit prio 3 `get_htb_adsll_string`
84
+
85
+$TC qdisc add dev $IFACE parent 1:11 handle 110: $QDISC `get_limit ${ELIMIT}` `get_target "${ETARGET}" ${UPLINK}` `get_ecn ${EECN}` `get_quantum 300` `get_flows ${PRIO_RATE}` ${EQDISC_OPTS}
86
+$TC qdisc add dev $IFACE parent 1:12 handle 120: $QDISC `get_limit ${ELIMIT}` `get_target "${ETARGET}" ${UPLINK}` `get_ecn ${EECN}` `get_quantum 300` `get_flows ${BE_RATE}` ${EQDISC_OPTS}
87
+$TC qdisc add dev $IFACE parent 1:13 handle 130: $QDISC `get_limit ${ELIMIT}` `get_target "${ETARGET}" ${UPLINK}` `get_ecn ${EECN}` `get_quantum 300` `get_flows ${BK_RATE}` ${EQDISC_OPTS}
88
+
89
+
90
+#sm: for testing we need a band to collect PPPOEd packets
91
+$TC class add dev $IFACE parent 1:1 classid 1:14 htb $LQ rate ${BE_RATE}kbit ceil ${BE_CEIL}kbit prio 2 `get_htb_adsll_string`
92
+$TC qdisc add dev $IFACE parent 1:14 handle 140: $QDISC `get_limit ${ELIMIT}` `get_target "${ETARGET}" ${UPLINK}` `get_ecn ${EECN}` `get_quantum 300` `get_flows ${BK_RATE}` ${EQDISC_OPTS}
93
+
94
+
95
+# Need a catchall rule (should also match VLANs and PPPoE packets)
96
+
97
+$TC filter add dev $IFACE parent 1:0 protocol all prio 999 u32 \
98
+        match ip protocol 0 0x00 flowid 1:12  
99
+
100
+# FIXME should probably change the filter here to do pre-nat
101
+        
102
+$TC filter add dev $IFACE parent 1:0 protocol ip prio 1 handle 1 fw classid 1:11
103
+$TC filter add dev $IFACE parent 1:0 protocol ip prio 2 handle 2 fw classid 1:12
104
+$TC filter add dev $IFACE parent 1:0 protocol ip prio 3 handle 3 fw classid 1:13
105
+
106
+# ipv6 support. Note that the handle indicates the fw mark bucket that is looked for
107
+
108
+$TC filter add dev $IFACE parent 1:0 protocol ipv6 prio 4 handle 1 fw classid 1:11
109
+$TC filter add dev $IFACE parent 1:0 protocol ipv6 prio 5 handle 2 fw classid 1:12
110
+$TC filter add dev $IFACE parent 1:0 protocol ipv6 prio 6 handle 3 fw classid 1:13
111
+
112
+# Arp traffic
113
+
114
+$TC filter add dev $IFACE parent 1:0 protocol arp prio 7 handle 1 fw classid 1:11
115
+
116
+# ICMP traffic - Don't impress your friends. Deoptimize to manage ping floods
117
+# better instead
118
+
119
+$TC filter add dev $IFACE parent 1:0 protocol ip prio 8 \
120
+	 u32 match ip protocol 1 0xff flowid 1:13
121
+
122
+$TC filter add dev $IFACE parent 1:0 protocol ipv6 prio 9 \
123
+	 u32 match ip protocol 1 0xff flowid 1:13
124
+
125
+
126
+
127
+
128
+# PPPoE encapsulated packets traversing the router (e.g.: the router does PPPoE termination but we shape 
129
+# on the underlaying ethernet interface instead of the pppoe device)
130
+
131
+PPPOE_SESSION_ETHERTYPE="0x8864"
132
+PPPOE_DISCOVERY_ETHERTYPE="0x8863"
133
+PPP_PROTO_IP4="0x0021"
134
+PPP_PROTO_IP6="0x0057"
135
+ARP_PROTO_IP4="0x0806"
136
+
137
+# NOTE it seems prio can not be reused?
138
+#$TC filter add dev $IFACE protocol 0x8863 parent 1:0 prio 1 u32 flowid 1:14
139
+# PPPoE can be selected for by ether_type, the encapsulated IP version from the PPP (0x0021 IPv4, 0x0057 IPv6)
140
+#U32_PREFIX="$TC filter add dev $IFACE" parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE}"
141
+
142
+#BE: 1:12 is the default anyway, but this will catch all non marked packets
143
+#$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 400 u32 \
144
+#	match u16 ${PPP_PROTO_IP4} 0xffff at 6 \
145
+#	match u8 0x00 0xfb at 9 \
146
+#	flowid 1:12
147
+
148
+#AF42
149
+$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 401 u32 \
150
+	match u16 ${PPP_PROTO_IP4} 0xffff at 6 \
151
+	match u8 0x90 0xfc at 9 \
152
+	flowid 1:11
153
+#EF
154
+$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 402 u32 \
155
+	match u16 ${PPP_PROTO_IP4} 0xffff at 6 \
156
+	match u8 0xb8 0xfc at 9 \
157
+	flowid 1:11
158
+#CS1
159
+$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 403 u32 \
160
+	match u16 ${PPP_PROTO_IP4} 0xffff at 6 \
161
+	match u8 0x20 0xf0 at 9 \
162
+	flowid 1:13
163
+#IMM
164
+$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 404 u32 \
165
+	match u16 ${PPP_PROTO_IP4} 0xffff at 6 \
166
+	match u8 0x10 0xf0 at 9 \
167
+	flowid 1:11
168
+#CS3
169
+$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 405 u32 \
170
+	match u16 ${PPP_PROTO_IP4} 0xffff at 6 \
171
+	match u8 0xc0 0xf0 at 9 \
172
+	flowid 1:11
173
+#CS6
174
+$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 406 u32 \
175
+	match u16 ${PPP_PROTO_IP4} 0xffff at 6 \
176
+	match u8 0xe0 0xf0 at 9 \
177
+	flowid 1:11
178
+
179
+
180
+## Arp traffic
181
+#$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 409 u32 \
182
+#	match u16 ${ARP_PROTO_IP4} 0xffff at 6 \
183
+#	flowid 1:14
184
+
185
+# ICMP traffic - Don't impress your friends. Deoptimize to manage ping floods
186
+# better instead; sm: really only deprio echo requestst and echo replies instead?
187
+# ECHO request, the rest stays in best effort
188
+$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 410 u32 \
189
+	match u16 ${PPP_PROTO_IP4} 0xffff at 6 \
190
+	match u8 0x01 0xff at 17 \
191
+	match u8 0x08 0xff at 28 \
192
+	flowid 1:13
193
+# ECHO reply
194
+$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 410 u32 \
195
+	match u16 ${PPP_PROTO_IP4} 0xffff at 6 \
196
+	match u8 0x01 0xff at 17 \
197
+	match u8 0x00 0xff at 28 \
198
+	flowid 1:13
199
+
200
+## ICMPv6 133-137 (NDP) is equivalent to IPv4 ARP, so only push echo request and reply into the bulk class
201
+## 133
202
+#$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 610 u32 \
203
+#	match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
204
+#	match u8 0x85 0xff at 48 \
205
+#	match u8 0x3a 0xff at 14 \
206
+#	flowid 1:14
207
+## 134
208
+#$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 610 u32 \
209
+#	match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
210
+#	match u8 0x86 0xff at 48 \
211
+#	match u8 0x3a 0xff at 14 \
212
+#	flowid 1:14
213
+## 135
214
+#$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 610 u32 \
215
+#	match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
216
+#	match u8 0x87 0xff at 48 \
217
+#	match u8 0x3a 0xff at 14 \
218
+#	flowid 1:14
219
+## 136
220
+#$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 610 u32 \
221
+#	match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
222
+#	match u8 0x88 0xff at 48 \
223
+#	match u8 0x3a 0xff at 14 \
224
+#	flowid 1:14
225
+## 137
226
+#$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 610 u32 \
227
+#	match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
228
+#	match u8 0x89 0xff at 48 \
229
+#	match u8 0x3a 0xff at 14 \
230
+#	flowid 1:14
231
+
232
+# ICMPv6 echo request
233
+$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 610 u32 \
234
+	match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
235
+	match u8 0x3a 0xff at 14 \
236
+	match u8 0x80 0xff at 48 \
237
+	flowid 1:13
238
+# ICMPv6 echo reply
239
+$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 610 u32 \
240
+	match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
241
+	match u8 0x3a 0xff at 14 \
242
+	match u8 0x81 0xff at 48 \
243
+	flowid 1:13
244
+
245
+
246
+
247
+
248
+#IPV6
249
+#BE: careful, will override ICMP
250
+#$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 600 u32 \
251
+#	match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
252
+#	match u16 0x0000 0x0fb0 at 8 \
253
+#	flowid 1:12
254
+#AF42
255
+$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 601 u32 \
256
+	match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
257
+	match u16 0x0900 0x0fc0 at 8 \
258
+	flowid 1:11
259
+#EF
260
+$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 602 u32 \
261
+	match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
262
+	match u16 0x0b80 0x0fc0 at 8 \
263
+	flowid 1:11
264
+#CS1
265
+$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 603 u32 \
266
+	match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
267
+	match u16 0x0200 0x0fc0 at 8 \
268
+	flowid 1:13
269
+#IMM
270
+$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 604 u32 \
271
+	match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
272
+	match u16 0x0100 0x0fc0 at 8 \
273
+	flowid 1:11
274
+#CS3
275
+$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 605 u32 \
276
+	match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
277
+	match u16 0x0c00 0x0fc0 at 8 \
278
+	flowid 1:11
279
+#CS6
280
+$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 606 u32 \
281
+	match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
282
+	match u16 0x0e00 0x0fc0 at 8 \
283
+	flowid 1:11
284
+
285
+
286
+
287
+
288
+#diffserv $IFACE
289
+
290
+}
291
+
292
+ingress() {
293
+
294
+CEIL=$DOWNLINK
295
+PRIO_RATE=`expr $CEIL / 3` # Ceiling for prioirty
296
+BE_RATE=`expr $CEIL / 6`   # Min for best effort
297
+BK_RATE=`expr $CEIL / 6`   # Min for background
298
+BE_CEIL=`expr $CEIL - 16`  # A little slop at the top
299
+
300
+LQ="quantum `get_mtu $IFACE $CEIL`"
301
+
302
+$TC qdisc del dev $IFACE handle ffff: ingress 2> /dev/null
303
+$TC qdisc add dev $IFACE handle ffff: ingress
304
+
305
+$TC qdisc del dev $DEV root  2> /dev/null
306
+
307
+if [ "$SQUASH_INGRESS" = "1" ]
308
+then
309
+sqm_logger "Do not perform DSCP based filtering on ingress. (1-tier classification)"
310
+# Revert to no dscp based filtering
311
+$TC qdisc del dev $DEV root 2>/dev/null
312
+$TC qdisc add dev $DEV root handle 1: `get_stab_string` htb default 10
313
+$TC class add dev $DEV parent 1: classid 1:1 htb $LQ rate ${DOWNLINK}kbit ceil ${DOWNLINK}kbit `get_htb_adsll_string`
314
+$TC class add dev $DEV parent 1:1 classid 1:10 htb $LQ rate ${DOWNLINK}kbit ceil ${DOWNLINK}kbit prio 0 `get_htb_adsll_string`
315
+$TC qdisc add dev $DEV parent 1:10 handle 110: $QDISC `get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_flows ${DOWNLINK}` ${IQDISC_OPTS}
316
+
317
+else
318
+sqm_logger "Perform DSCP based filtering on ingress. (3-tier classification)"
319
+$TC qdisc add dev $DEV root handle 1: `get_stab_string` htb default 12
320
+$TC class add dev $DEV parent 1: classid 1:1 htb $LQ rate ${CEIL}kbit ceil ${CEIL}kbit `get_htb_adsll_string`
321
+$TC class add dev $DEV parent 1:1 classid 1:10 htb $LQ rate ${CEIL}kbit ceil ${CEIL}kbit prio 0 `get_htb_adsll_string`
322
+$TC class add dev $DEV parent 1:1 classid 1:11 htb $LQ rate 32kbit ceil ${PRIO_RATE}kbit prio 1 `get_htb_adsll_string`
323
+$TC class add dev $DEV parent 1:1 classid 1:12 htb $LQ rate ${BE_RATE}kbit ceil ${BE_CEIL}kbit prio 2 `get_htb_adsll_string`
324
+$TC class add dev $DEV parent 1:1 classid 1:13 htb $LQ rate ${BK_RATE}kbit ceil ${BE_CEIL}kbit prio 3 `get_htb_adsll_string`
325
+
326
+# I'd prefer to use a pre-nat filter but that causes permutation...
327
+
328
+$TC qdisc add dev $DEV parent 1:11 handle 110: $QDISC `get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_quantum 500` `get_flows ${PRIO_RATE}` ${IQDISC_OPTS}
329
+$TC qdisc add dev $DEV parent 1:12 handle 120: $QDISC `get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_quantum 1500` `get_flows ${BE_RATE}` ${IQDISC_OPTS}
330
+$TC qdisc add dev $DEV parent 1:13 handle 130: $QDISC `get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_quantum 300` `get_flows ${BK_RATE}` ${IQDISC_OPTS}
331
+
332
+#sm: for PPPoE packet testing
333
+$TC class add dev $DEV parent 1:1 classid 1:14 htb $LQ rate ${BK_RATE}kbit ceil ${BE_CEIL}kbit prio 3 `get_htb_adsll_string`
334
+$TC qdisc add dev $DEV parent 1:14 handle 140: $QDISC `get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_quantum 300` `get_flows ${BK_RATE}` ${IQDISC_OPTS}
335
+
336
+
337
+
338
+#diffserv $DEV
339
+diffserv_pppoe $DEV
340
+
341
+fi
342
+
343
+ifconfig $DEV up
344
+
345
+# redirect all IP packets arriving in $IFACE to ifb0 
346
+
347
+$TC filter add dev $IFACE parent ffff: protocol all prio 10 u32 \
348
+  match u32 0 0 flowid 1:1 action mirred egress redirect dev $DEV
349
+
350
+}
351
+
352
+do_modules
353
+ipt_setup
354
+
355
+if [ "$UPLINK" -ne 0 ];
356
+then
357
+	egress
358
+	sqm_logger "egress shaping activated"
359
+else
360
+	sqm_logger "egress shaping deactivated"
361
+	tc qdisc del dev $IFACE root 2> /dev/null
362
+fi
363
+if [ "$DOWNLINK" -ne 0 ];
364
+then
365
+	ingress
366
+	sqm_logger "ingress shaping activated"
367
+else
368
+	sqm_logger "ingress shaping deactivated"
369
+	tc qdisc del dev $DEV root 2> /dev/null
370
+	tc qdisc del dev $IFACE ingress 2> /dev/null
371
+fi
372
+
373
+
374
+
375
+# References:
376
+# This alternate shaper attempts to go for 1/u performance in a clever way
377
+# http://git.coverfire.com/?p=linux-qos-scripts.git;a=blob;f=src-3tos.sh;hb=HEAD
378
+
379
+# Comments
380
+# This does the right thing with ipv6 traffic.
381
+# It also tries to leverage diffserv to some sane extent. In particular,
382
+# the 'priority' queue is limited to 33% of the total, so EF, and IMM traffic
383
+# cannot starve other types. The rfc suggested 30%. 30% is probably
384
+# a lot in today's world.
385
+
386
+# Flaws
387
+# Many!

+ 2
- 0
net/sqm-scripts/files/usr/lib/sqm/simple_pppoe.qos.help View File

@@ -0,0 +1,2 @@
1
+BW-limited three-tier prioritisation scheme with fq_codel on each queue. Temporary version to implement shaping
2
+of pass through PPPOE encapsulated packets.

+ 81
- 0
net/sqm-scripts/files/usr/lib/sqm/simplest.qos View File

@@ -0,0 +1,81 @@
1
+#!/bin/sh
2
+# Cero3 Simple Shaper
3
+# A 1 bin tc_codel and ipv6 enabled shaping script for
4
+# ethernet gateways. This is nearly the simplest possible
5
+
6
+# Copyright (C) 2013 Michael D Taht
7
+# GPLv2
8
+
9
+. /usr/lib/sqm/functions.sh
10
+sqm_logger "Starting simplest.qos"
11
+
12
+egress() {
13
+
14
+LQ="quantum `get_mtu $IFACE ${UPLINK}`"
15
+
16
+$TC qdisc del dev $IFACE root 2>/dev/null
17
+$TC qdisc add dev $IFACE root handle 1: `get_stab_string` htb default 10
18
+$TC class add dev $IFACE parent 1: classid 1:1 htb $LQ rate ${UPLINK}kbit ceil ${UPLINK}kbit `get_htb_adsll_string`
19
+$TC class add dev $IFACE parent 1:1 classid 1:10 htb $LQ rate ${UPLINK}kbit ceil ${UPLINK}kbit prio 0 `get_htb_adsll_string`
20
+$TC qdisc add dev $IFACE parent 1:10 handle 110: $QDISC `get_limit ${ELIMIT}` `get_target "${ETARGET}" ${UPLINK}` `get_ecn ${EECN}` `get_flows ${UPLINK}` ${EQDISC_OPTS}
21
+
22
+}
23
+
24
+
25
+ingress() {
26
+sqm_logger "ingress"
27
+$TC qdisc del dev $IFACE handle ffff: ingress 2>/dev/null
28
+$TC qdisc add dev $IFACE handle ffff: ingress
29
+
30
+LQ="quantum `get_mtu $IFACE ${DOWNLINK}`"
31
+ 
32
+$TC qdisc del dev $DEV root 2>/dev/null
33
+$TC qdisc add dev $DEV root handle 1: `get_stab_string` htb default 10
34
+$TC class add dev $DEV parent 1: classid 1:1 htb $LQ rate ${DOWNLINK}kbit ceil ${DOWNLINK}kbit `get_htb_adsll_string`
35
+$TC class add dev $DEV parent 1:1 classid 1:10 htb $LQ rate ${DOWNLINK}kbit ceil ${DOWNLINK}kbit prio 0 `get_htb_adsll_string`
36
+
37
+# FIXME: I'd prefer to use a pre-nat filter but we need to detect if nat is on this interface
38
+# AND we need to permute by a random number which we can't do from userspace filters
39
+
40
+# Most high rate flows are REALLY close. This stomps on those harder, but hurts on high rate long distance
41
+#$TC qdisc add dev $DEV parent 1:10 handle 110: $QDISC limit $LIMIT $ECN interval 20ms target 3ms `get_flows ${DOWNLINK}`
42
+$TC qdisc add dev $DEV parent 1:10 handle 110: $QDISC `get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_flows ${DOWNLINK}` ${IQDISC_OPTS}
43
+
44
+ifconfig $DEV up
45
+
46
+# redirect all IP packets arriving in $IFACE to ifb0 
47
+
48
+$TC filter add dev $IFACE parent ffff: protocol all prio 10 u32 \
49
+  match u32 0 0 flowid 1:1 action mirred egress redirect dev $DEV
50
+
51
+}
52
+
53
+do_modules
54
+
55
+if [ "$UPLINK" -ne 0 ];
56
+then
57
+	egress
58
+	sqm_logger "egress shaping activated"
59
+else
60
+	sqm_logger "egress shaping deactivated"
61
+	tc qdisc del dev $IFACE root 2> /dev/null
62
+fi
63
+if [ "$DOWNLINK" -ne 0 ];
64
+then
65
+	ingress
66
+	sqm_logger "ingress shaping activated"
67
+else
68
+	sqm_logger "ingress shaping deactivated"
69
+	tc qdisc del dev $DEV root 2> /dev/null
70
+	tc qdisc del dev $IFACE ingress 2> /dev/null
71
+fi
72
+
73
+
74
+# References:
75
+# This alternate shaper attempts to go for 1/u performance in a clever way
76
+# http://git.coverfire.com/?p=linux-qos-scripts.git;a=blob;f=src-3tos.sh;hb=HEAD
77
+
78
+# Comments
79
+# This does the right thing with ipv6 traffic.
80
+# Flaws
81
+# Many!

+ 1
- 0
net/sqm-scripts/files/usr/lib/sqm/simplest.qos.help View File

@@ -0,0 +1 @@
1
+Simplest possible configuration: HTB rate limiter with your qdisc attached.

+ 35
- 0
net/sqm-scripts/files/usr/lib/sqm/stop.sh View File

@@ -0,0 +1,35 @@
1
+#!/bin/sh
2
+
3
+. /usr/lib/sqm/functions.sh
4
+
5
+# allow passing in the IFACE as first command line argument
6
+[ ! -z ${1} ] && IFACE=${1}
7
+sqm_logger "${0} Stopping ${IFACE}"
8
+
9
+# make sure to only delete the ifb associated with the current interface
10
+CUR_IFB=$( get_ifb_associated_with_if ${IFACE} )
11
+
12
+sqm_stop() {
13
+	tc qdisc del dev $IFACE ingress 2> /dev/null
14
+	tc qdisc del dev $IFACE root 2> /dev/null
15
+	[ ! -z "$CUR_IFB" ] && tc qdisc del dev $CUR_IFB root 2> /dev/null
16
+        [ ! -z "$CUR_IFB" ] && sqm_logger "${CUR_IFB} shaper deleted"
17
+}
18
+
19
+ipt_stop() {
20
+	[ ! -z "$CUR_IFB" ] && ipt -t mangle -D POSTROUTING -o $CUR_IFB -m mark --mark 0x00 -g QOS_MARK_${IFACE} 
21
+	ipt -t mangle -D POSTROUTING -o $IFACE -m mark --mark 0x00 -g QOS_MARK_${IFACE} 
22
+	ipt -t mangle -D PREROUTING -i vtun+ -p tcp -j MARK --set-mark 0x2
23
+	ipt -t mangle -D OUTPUT -p udp -m multiport --ports 123,53 -j DSCP --set-dscp-class AF42
24
+	ipt -t mangle -F QOS_MARK_${IFACE}
25
+	ipt -t mangle -X QOS_MARK_${IFACE}
26
+}
27
+
28
+
29
+sqm_stop
30
+ipt_stop
31
+[ ! -z "$CUR_IFB" ] && ifconfig ${CUR_IFB} down
32
+[ ! -z "$CUR_IFB" ] && ip link delete ${CUR_IFB} type ifb
33
+[ ! -z "$CUR_IFB" ] && sqm_logger "${CUR_IFB} interface deleted"
34
+
35
+exit 0