update qos-scripts to v1.1 - rewritten hfsc rate calculation

SVN-Revision: 6875
This commit is contained in:
Felix Fietkau 2007-04-06 16:59:56 +00:00
parent c6aa5d159d
commit c993ad73be
7 changed files with 158 additions and 154 deletions

View file

@ -9,7 +9,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=qos-scripts PKG_NAME:=qos-scripts
PKG_VERSION:=0.9.4 PKG_VERSION:=1.1.0
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)

View file

@ -60,35 +60,29 @@ config classgroup "Default"
config class "Priority" config class "Priority"
option packetsize 300 option packetsize 400
option packetdelay 10
option maxsize 400 option maxsize 400
option avgrate 40 option avgrate 10
option linksharing 75 option priority 20
config class "Priority_down" config class "Priority_down"
option packetsize 1500 option packetsize 1000
option avgrate 20 option avgrate 10
config class "Express" config class "Express"
option packetsize 1300 option packetsize 1000
option packetdelay 15
option maxsize 800 option maxsize 800
option avgrate 30 option avgrate 50
option linksharing 80 option priority 10
config class "Normal" config class "Normal"
option packetsize 1500 option packetsize 1500
option packetdelay 150 option packetdelay 100
option avgrate 20 option avgrate 10
option linksharing 30 option priority 5
config class "Normal_down" config class "Normal_down"
option avgrate 30 option avgrate 20
config class "Bulk" config class "Bulk"
option linksharing 10 option avgrate 1
config class "Bulk_down" option packetdelay 200
option avgrate 15
option limitrate 85

View file

@ -1,2 +1,2 @@
#!/bin/sh #!/bin/sh
[ "$ACTION" = ifup ] && /usr/lib/qos.sh interface "$INTERFACE" | sh [ "$ACTION" = ifup ] && /usr/lib/qos/generate.sh interface "$INTERFACE" | sh

View file

@ -4,7 +4,7 @@
START=50 START=50
boot() { boot() {
/usr/lib/qos.sh firewall | sh /usr/lib/qos/generate.sh firewall | sh
} }
start() { start() {

View file

@ -1,4 +1,4 @@
#!/bin/sh #!/bin/sh
qos-stop qos-stop
/usr/lib/qos.sh all | sh /usr/lib/qos/generate.sh all | sh

View file

@ -1,8 +1,6 @@
#!/bin/sh #!/bin/sh
. /etc/functions.sh [ -e /etc/functions.sh ] && . /etc/functions.sh || . ./functions.sh
[ -x /sbin/modprobe ] && insmod="modprobe" || insmod="insmod"
insmod="insmod"
[ -f /sbin/modprobe ] && insmod="modprobe"
add_insmod() { add_insmod() {
eval "export isset=\${insmod_$1}" eval "export isset=\${insmod_$1}"
@ -12,11 +10,20 @@ add_insmod() {
esac esac
} }
find_ifname() {( [ -e /etc/config/network ] && {
include /lib/network # only try to parse network config on openwrt
scan_interfaces
config_get "$1" ifname find_ifname() {(
)} include /lib/network
scan_interfaces
config_get "$1" ifname
)}
} || {
find_ifname() {
echo "Interface not found."
exit 1
}
}
parse_matching_rule() { parse_matching_rule() {
local var="$1" local var="$1"
@ -182,110 +189,6 @@ config_cb() {
esac 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() { enum_classes() {
local c="0" local c="0"
@ -315,6 +218,15 @@ cls_var() {
export ${varname}="${tmp:-$default}" 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() { start_interface() {
local iface="$1" local iface="$1"
local num_imq="$2" local num_imq="$2"
@ -331,7 +243,7 @@ start_interface() {
for dir in up${halfduplex} ${download:+down}; do for dir in up${halfduplex} ${download:+down}; do
case "$dir" in case "$dir" in
up) up)
upload=$(($upload * 98 / 100 - 10)) upload=$(($upload * 98 / 100 - (32 * 128 / $upload)))
dev="$device" dev="$device"
rate="$upload" rate="$upload"
dl_mode="" dl_mode=""
@ -340,7 +252,7 @@ start_interface() {
down) down)
add_insmod imq numdevs="$num_imq" add_insmod imq numdevs="$num_imq"
config_get imqdev "$iface" imqdev config_get imqdev "$iface" imqdev
download=$(($download * 96 / 100 - 64)) download=$(($download * 98 / 100 - (100 * 1024 / $download)))
dev="imq$imqdev" dev="imq$imqdev"
rate="$download" rate="$download"
dl_mode=1 dl_mode=1
@ -348,22 +260,17 @@ start_interface() {
;; ;;
*) continue;; *) continue;;
esac esac
cstr=
for class in $classes; do for class in $classes; do
cls_var umax "$class" packetsize $dir 1500 cls_var pktsize "$class" packetsize $dir 1500
cls_var dmax "$class" packetdelay $dir 500 cls_var pktdelay "$class" packetdelay $dir 0
cls_var maxrate "$class" limitrate $dir 100 cls_var maxrate "$class" limitrate $dir 100
cls_var share "$class" linksharing $dir 0 cls_var prio "$class" priority $dir 1
cls_var m2 "$class" avgrate $dir 0 cls_var avgrate "$class" avgrate $dir 0
maxrate=$(($maxrate * $rate / 100))
share=$(($share * $rate / 100))
m2=$(($m2 * $rate / 100))
config_get classnr "$class" classnr config_get classnr "$class" classnr
append ${prefix}q "$(class_main_qdisc "$dev" "$iface")" "$N" append cstr "$classnr:$prio:$avgrate:$pktsize:$pktdelay:$maxrate" "$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"
done done
append ${prefix}q "$(tcrules)" "$N"
export dev_${dir}="ifconfig $dev up txqueuelen 5 >&- 2>&- export dev_${dir}="ifconfig $dev up txqueuelen 5 >&- 2>&-
tc qdisc del dev $dev root >&- 2>&- tc qdisc del dev $dev root >&- 2>&-
tc qdisc add dev $dev root handle 1: hfsc default ${class_default}0 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_hfsc
add_insmod sch_sfq add_insmod sch_sfq
add_insmod sch_red add_insmod sch_red
cat <<EOF cat <<EOF
${INSMOD:+$INSMOD$N}${dev_up:+$dev_up ${INSMOD:+$INSMOD$N}${dev_up:+$dev_up
$clsq $clsq
$clsl
$clsf
}${imqdev:+$dev_down }${imqdev:+$dev_down
$d_clsq $d_clsq
$d_clsl $d_clsl
@ -471,7 +377,10 @@ EOF
C="0" C="0"
INTERFACES="" INTERFACES=""
config_load qos [ -e ./qos.conf ] && {
. ./qos.conf
config_cb
} || config_load qos
C="0" C="0"
for iface in $INTERFACES; do for iface in $INTERFACES; do

View 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"
}
}