update qos-scripts to v1.1 - rewritten hfsc rate calculation
SVN-Revision: 6875
This commit is contained in:
parent
c6aa5d159d
commit
c993ad73be
7 changed files with 158 additions and 154 deletions
|
@ -9,7 +9,7 @@
|
|||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=qos-scripts
|
||||
PKG_VERSION:=0.9.4
|
||||
PKG_VERSION:=1.1.0
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
||||
|
|
|
@ -60,35 +60,29 @@ config classgroup "Default"
|
|||
|
||||
|
||||
config class "Priority"
|
||||
option packetsize 300
|
||||
option packetdelay 10
|
||||
option packetsize 400
|
||||
option maxsize 400
|
||||
option avgrate 40
|
||||
option linksharing 75
|
||||
option avgrate 10
|
||||
option priority 20
|
||||
config class "Priority_down"
|
||||
option packetsize 1500
|
||||
option avgrate 20
|
||||
option packetsize 1000
|
||||
option avgrate 10
|
||||
|
||||
|
||||
config class "Express"
|
||||
option packetsize 1300
|
||||
option packetdelay 15
|
||||
option packetsize 1000
|
||||
option maxsize 800
|
||||
option avgrate 30
|
||||
option linksharing 80
|
||||
|
||||
option avgrate 50
|
||||
option priority 10
|
||||
|
||||
config class "Normal"
|
||||
option packetsize 1500
|
||||
option packetdelay 150
|
||||
option avgrate 20
|
||||
option linksharing 30
|
||||
option packetdelay 100
|
||||
option avgrate 10
|
||||
option priority 5
|
||||
config class "Normal_down"
|
||||
option avgrate 30
|
||||
|
||||
option avgrate 20
|
||||
|
||||
config class "Bulk"
|
||||
option linksharing 10
|
||||
config class "Bulk_down"
|
||||
option avgrate 15
|
||||
option limitrate 85
|
||||
option avgrate 1
|
||||
option packetdelay 200
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#!/bin/sh
|
||||
[ "$ACTION" = ifup ] && /usr/lib/qos.sh interface "$INTERFACE" | sh
|
||||
[ "$ACTION" = ifup ] && /usr/lib/qos/generate.sh interface "$INTERFACE" | sh
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
START=50
|
||||
|
||||
boot() {
|
||||
/usr/lib/qos.sh firewall | sh
|
||||
/usr/lib/qos/generate.sh firewall | sh
|
||||
}
|
||||
|
||||
start() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
qos-stop
|
||||
/usr/lib/qos.sh all | sh
|
||||
/usr/lib/qos/generate.sh all | sh
|
||||
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#!/bin/sh
|
||||
. /etc/functions.sh
|
||||
|
||||
insmod="insmod"
|
||||
[ -f /sbin/modprobe ] && insmod="modprobe"
|
||||
[ -e /etc/functions.sh ] && . /etc/functions.sh || . ./functions.sh
|
||||
[ -x /sbin/modprobe ] && insmod="modprobe" || insmod="insmod"
|
||||
|
||||
add_insmod() {
|
||||
eval "export isset=\${insmod_$1}"
|
||||
|
@ -12,11 +10,20 @@ add_insmod() {
|
|||
esac
|
||||
}
|
||||
|
||||
[ -e /etc/config/network ] && {
|
||||
# only try to parse network config on openwrt
|
||||
|
||||
find_ifname() {(
|
||||
include /lib/network
|
||||
scan_interfaces
|
||||
config_get "$1" ifname
|
||||
)}
|
||||
} || {
|
||||
find_ifname() {
|
||||
echo "Interface not found."
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
parse_matching_rule() {
|
||||
local var="$1"
|
||||
|
@ -182,110 +189,6 @@ config_cb() {
|
|||
esac
|
||||
}
|
||||
|
||||
class_main_qdisc() {
|
||||
local device="$1"
|
||||
awk -f - <<EOF
|
||||
BEGIN {
|
||||
limit = int("$maxrate")
|
||||
m2 = int("$m2")
|
||||
dmax = int("$dmax")
|
||||
umax = int("$umax")
|
||||
share = int("$share")
|
||||
|
||||
if (!(m2 > 0)) {
|
||||
dmax = 500
|
||||
umax = 1500
|
||||
m2 = 10
|
||||
rt = 0
|
||||
} else {
|
||||
rt = 1
|
||||
}
|
||||
|
||||
cdata = ""
|
||||
pdmax = int (dmax + (umax * 8 / limit))
|
||||
if (rt == 1) {
|
||||
if (share > 0) cdata = " rt"
|
||||
else cdata = " ls"
|
||||
if ((umax > 0) && (dmax > 0)) {
|
||||
cdata = cdata " umax " umax "b dmax " pdmax "ms"
|
||||
}
|
||||
cdata = cdata " rate " m2 "kbit"
|
||||
}
|
||||
if (share > 0) {
|
||||
if ((m2 > 0) && (umax > 0) && (dmax > 0)) {
|
||||
cdata = cdata " ls umax " umax "b dmax " pdmax "ms rate " share "kbit"
|
||||
} else {
|
||||
cdata = cdata " ls m1 " share "kbit d 500ms m2 " share "kbit"
|
||||
}
|
||||
}
|
||||
|
||||
print "tc class add dev $device parent 1:1 classid 1:${classnr}0 hfsc" cdata " ul rate " limit "kbit"
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
class_leaf_qdisc() {
|
||||
local device="$1"
|
||||
awk -f - <<EOF
|
||||
|
||||
function qlen(rate, m2, umax, dmax, qb, qr, qt, ql) {
|
||||
qlen_min = 5 # minimum queue length
|
||||
qlen_base = 1.7 # base value - queueing time in seconds
|
||||
qlen_avgr = 0.7 # avgrate modifier
|
||||
qlen_dmax = 0.0 # dmax modifier
|
||||
|
||||
# bits in a packet
|
||||
qb = 1500
|
||||
if ((m2 > 0) && (umax > 0)) qb -= int((1500 - umax) * qlen_pkt)
|
||||
qb *= 8
|
||||
|
||||
# rate in bits/s
|
||||
qr = rate
|
||||
qr -= int((rate - m2) * qlen_avgr)
|
||||
qr *= 1024
|
||||
|
||||
# queue time
|
||||
qt = qlen_base + qlen_dmax * (dmax / 1000)
|
||||
|
||||
# queue length
|
||||
ql = int(qr * qt / qb)
|
||||
if (ql < qlen_min) ql = qlen_min
|
||||
|
||||
return ql
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
sfq_dthresh = 25 # use sfq for download if pktdelay set to this or lower
|
||||
|
||||
limit = int("$maxrate")
|
||||
m2 = int("$m2")
|
||||
dmax = int("$dmax")
|
||||
umax = int("$umax")
|
||||
|
||||
if (!(m2 > 0)) {
|
||||
dmax = 500
|
||||
umax = 1500
|
||||
m2 = 10
|
||||
}
|
||||
|
||||
cqlen = ${dl_mode:+2 * }qlen(limit, m2, umax, dmax)
|
||||
|
||||
printf "tc qdisc add dev $device parent 1:${classnr}0 handle ${classnr}00: "
|
||||
if (("$dir" != "down") || ((dmax > 0) && (dmax <= sfq_dthresh))) {
|
||||
print "sfq perturb 10 limit " cqlen
|
||||
} else {
|
||||
avpkt = 1200
|
||||
if (min < avpkt) min = avpkt
|
||||
min = int(limit * 1024 / 8 * 0.1)
|
||||
dqb = cqlen * 1500
|
||||
max = int(min + (dqb - min) * 0.25)
|
||||
burst = int((2 * min + max) / (3 * avpkt))
|
||||
|
||||
print "red min " min " max " max " burst " burst " avpkt " avpkt " limit " dqb " probability 0.04 ecn"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
enum_classes() {
|
||||
local c="0"
|
||||
|
@ -315,6 +218,15 @@ cls_var() {
|
|||
export ${varname}="${tmp:-$default}"
|
||||
}
|
||||
|
||||
tcrules() {
|
||||
dir=/usr/lib/qos
|
||||
[ -e $dir/tcrules.awk ] || dir=.
|
||||
echo "$cstr" | awk \
|
||||
-v device="$dev" \
|
||||
-v linespeed="$rate" \
|
||||
-f $dir/tcrules.awk
|
||||
}
|
||||
|
||||
start_interface() {
|
||||
local iface="$1"
|
||||
local num_imq="$2"
|
||||
|
@ -331,7 +243,7 @@ start_interface() {
|
|||
for dir in up${halfduplex} ${download:+down}; do
|
||||
case "$dir" in
|
||||
up)
|
||||
upload=$(($upload * 98 / 100 - 10))
|
||||
upload=$(($upload * 98 / 100 - (32 * 128 / $upload)))
|
||||
dev="$device"
|
||||
rate="$upload"
|
||||
dl_mode=""
|
||||
|
@ -340,7 +252,7 @@ start_interface() {
|
|||
down)
|
||||
add_insmod imq numdevs="$num_imq"
|
||||
config_get imqdev "$iface" imqdev
|
||||
download=$(($download * 96 / 100 - 64))
|
||||
download=$(($download * 98 / 100 - (100 * 1024 / $download)))
|
||||
dev="imq$imqdev"
|
||||
rate="$download"
|
||||
dl_mode=1
|
||||
|
@ -348,22 +260,17 @@ start_interface() {
|
|||
;;
|
||||
*) continue;;
|
||||
esac
|
||||
cstr=
|
||||
for class in $classes; do
|
||||
cls_var umax "$class" packetsize $dir 1500
|
||||
cls_var dmax "$class" packetdelay $dir 500
|
||||
|
||||
cls_var pktsize "$class" packetsize $dir 1500
|
||||
cls_var pktdelay "$class" packetdelay $dir 0
|
||||
cls_var maxrate "$class" limitrate $dir 100
|
||||
cls_var share "$class" linksharing $dir 0
|
||||
cls_var m2 "$class" avgrate $dir 0
|
||||
maxrate=$(($maxrate * $rate / 100))
|
||||
share=$(($share * $rate / 100))
|
||||
m2=$(($m2 * $rate / 100))
|
||||
|
||||
cls_var prio "$class" priority $dir 1
|
||||
cls_var avgrate "$class" avgrate $dir 0
|
||||
config_get classnr "$class" classnr
|
||||
append ${prefix}q "$(class_main_qdisc "$dev" "$iface")" "$N"
|
||||
append ${prefix}l "$(class_leaf_qdisc "$dev" "$iface")" "$N"
|
||||
append ${prefix}f "tc filter add dev $dev parent 1: prio $classnr protocol ip handle $classnr fw flowid 1:${classnr}0" "$N"
|
||||
append cstr "$classnr:$prio:$avgrate:$pktsize:$pktdelay:$maxrate" "$N"
|
||||
done
|
||||
append ${prefix}q "$(tcrules)" "$N"
|
||||
export dev_${dir}="ifconfig $dev up txqueuelen 5 >&- 2>&-
|
||||
tc qdisc del dev $dev root >&- 2>&-
|
||||
tc qdisc add dev $dev root handle 1: hfsc default ${class_default}0
|
||||
|
@ -373,11 +280,10 @@ tc class add dev $dev parent 1: classid 1:1 hfsc sc rate ${rate}kbit ul rate ${r
|
|||
add_insmod sch_hfsc
|
||||
add_insmod sch_sfq
|
||||
add_insmod sch_red
|
||||
|
||||
cat <<EOF
|
||||
${INSMOD:+$INSMOD$N}${dev_up:+$dev_up
|
||||
$clsq
|
||||
$clsl
|
||||
$clsf
|
||||
}${imqdev:+$dev_down
|
||||
$d_clsq
|
||||
$d_clsl
|
||||
|
@ -471,7 +377,10 @@ EOF
|
|||
|
||||
C="0"
|
||||
INTERFACES=""
|
||||
config_load qos
|
||||
[ -e ./qos.conf ] && {
|
||||
. ./qos.conf
|
||||
config_cb
|
||||
} || config_load qos
|
||||
|
||||
C="0"
|
||||
for iface in $INTERFACES; do
|
101
package/qos-scripts/files/usr/lib/qos/tcrules.awk
Normal file
101
package/qos-scripts/files/usr/lib/qos/tcrules.awk
Normal file
|
@ -0,0 +1,101 @@
|
|||
BEGIN {
|
||||
dmax=100
|
||||
if (!(linespeed > 0)) linespeed = 128
|
||||
FS=":"
|
||||
n = 0
|
||||
}
|
||||
|
||||
($1 != "") {
|
||||
n++
|
||||
class[n] = $1
|
||||
prio[n] = $2
|
||||
avgrate[n] = ($3 * linespeed / 100)
|
||||
pktsize[n] = $4
|
||||
delay[n] = $5
|
||||
maxrate[n] = ($6 * linespeed / 100)
|
||||
}
|
||||
|
||||
END {
|
||||
allocated = 0
|
||||
maxdelay = 0
|
||||
|
||||
for (i = 1; i <= n; i++) {
|
||||
# set defaults
|
||||
if (!(pktsize[i] > 0)) pktsize[i] = 1500
|
||||
if (!(prio[i] > 0)) prio[i] = 1
|
||||
|
||||
allocated += avgrate[i]
|
||||
sum_prio += prio[i]
|
||||
if ((avgrate[i] > 0) && !(delay[i] > 0)) {
|
||||
sum_rtprio += prio[i]
|
||||
}
|
||||
}
|
||||
|
||||
# allocation of m1 in rt classes:
|
||||
# sum(d * m1) must not exceed dmax * (linespeed - allocated)
|
||||
dmax = 0
|
||||
for (i = 1; i <= n; i++) {
|
||||
if (avgrate[i] > 0) {
|
||||
rtm2[i] = avgrate[i]
|
||||
if (delay[i] > 0) {
|
||||
d[i] = delay[i]
|
||||
} else {
|
||||
d[i] = 2 * pktsize[i] * 1000 / (linespeed * 1024)
|
||||
if (d[i] > dmax) dmax = d[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ds_avail = dmax * (linespeed - allocated)
|
||||
for (i = 1; i <= n; i++) {
|
||||
lsm1[i] = 0
|
||||
rtm1[i] = 0
|
||||
lsm2[i] = linespeed * prio[i] / sum_prio
|
||||
if ((avgrate[i] > 0) && (d[i] > 0)) {
|
||||
if (!(delay[i] > 0)) {
|
||||
ds = ds_avail * prio[i] / sum_rtprio
|
||||
ds_avail -= ds
|
||||
rtm1[i] = rtm2[i] + ds/d[i]
|
||||
}
|
||||
lsm1[i] = rtm1[i]
|
||||
}
|
||||
else {
|
||||
d[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
# main qdisc
|
||||
for (i = 1; i <= n; i++) {
|
||||
printf "tc class add dev "device" parent 1:1 classid 1:"class[i]"0 hfsc"
|
||||
if (rtm1[i] > 0) {
|
||||
printf " rt m1 " int(rtm1[i]) "kbit d " int(d[i] * 1000) "us m2 " int(rtm2[i])"kbit"
|
||||
}
|
||||
printf " ls m1 " int(lsm1[i]) "kbit d " int(d[i] * 1000) "us m2 " int(lsm2[i]) "kbit"
|
||||
print " ul rate " int(maxrate[i]) "kbit"
|
||||
}
|
||||
|
||||
# leaf qdisc
|
||||
avpkt = 1200
|
||||
for (i = 1; i <= n; i++) {
|
||||
ql = int((avgrate[i] + linespeed) * 1024 / (8 * pktsize[i]))
|
||||
printf "tc qdisc add dev "device" parent 1:"class[i]"0 handle "class[i]"00: "
|
||||
if (rtm1[i] > 0) {
|
||||
# rt class - use sfq
|
||||
print "sfq perturb 2 limit " ql
|
||||
} else {
|
||||
# non-rt class - use red
|
||||
min = int(maxrate[i] * 1024 / 8 * 0.05)
|
||||
if (min < avpkt) min = avpkt
|
||||
dqb = 8 * min;
|
||||
max = int(2.1*min)
|
||||
rburst = int((1.5*min + max) / (3 * avpkt))
|
||||
print "red min " min " max " max " burst " rburst " avpkt " avpkt " limit " dqb " probability 0.04 ecn"
|
||||
}
|
||||
}
|
||||
|
||||
# filter rule
|
||||
for (i = 1; i <= n; i++) {
|
||||
print "tc filter add dev "device" parent 1: prio "class[i]" protocol ip handle "class[i]" fw flowid 1:"class[i] "0"
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in a new issue