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
|
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)
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
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