qos-scripts: fix RED burst calculation
[openwrt.git] / package / qos-scripts / files / usr / lib / qos / tcrules.awk
1 BEGIN {
2         dmax=100
3         if (!(linespeed > 0)) linespeed = 128
4         FS=":"
5         n = 0
6 }
7
8 ($1 != "") {
9         n++
10         class[n] = $1
11         prio[n] = $2
12         avgrate[n] = ($3 * linespeed / 100)
13         pktsize[n] = $4
14         delay[n] = $5
15         maxrate[n] = ($6 * linespeed / 100)
16 }
17
18 END {
19         allocated = 0
20         maxdelay = 0
21
22         for (i = 1; i <= n; i++) {
23                 # set defaults
24                 if (!(pktsize[i] > 0)) pktsize[i] = 1500
25                 if (!(prio[i] > 0)) prio[i] = 1
26
27                 allocated += avgrate[i]
28                 sum_prio += prio[i]
29                 if ((avgrate[i] > 0) && !(delay[i] > 0)) {
30                         sum_rtprio += prio[i]
31                 }
32         }
33         
34         # allocation of m1 in rt classes:
35         # sum(d * m1) must not exceed dmax * (linespeed - allocated)
36         dmax = 0
37         for (i = 1; i <= n; i++) {
38                 if (avgrate[i] > 0) {
39                         rtm2[i] = avgrate[i]
40                         if (delay[i] > 0) {
41                                 d[i] = delay[i]
42                         } else {
43                                 d[i] = 2 * pktsize[i] * 1000 / (linespeed * 1024)
44                                 if (d[i] > dmax) dmax = d[i]
45                         }
46                 }
47         }       
48
49         ds_avail = dmax * (linespeed - allocated)
50         for (i = 1; i <= n; i++) {
51                 lsm1[i] = 0
52                 rtm1[i] = 0
53                 lsm2[i] = linespeed * prio[i] / sum_prio
54                 if ((avgrate[i] > 0) && (d[i] > 0)) {
55                         if (!(delay[i] > 0)) {
56                                 ds = ds_avail * prio[i] / sum_rtprio
57                                 ds_avail -= ds
58                                 rtm1[i] = rtm2[i] + ds/d[i]
59                         }
60                         lsm1[i] = rtm1[i]
61                 }
62                 else {
63                         d[i] = 0
64                 }
65         }
66
67         # main qdisc
68         for (i = 1; i <= n; i++) {
69                 printf "tc class add dev "device" parent 1:1 classid 1:"class[i]"0 hfsc"
70                 if (rtm1[i] > 0) {
71                         printf " rt m1 " int(rtm1[i]) "kbit d " int(d[i] * 1000) "us m2 " int(rtm2[i])"kbit"
72                 }
73                 printf " ls m1 " int(lsm1[i]) "kbit d " int(d[i] * 1000) "us m2 " int(lsm2[i]) "kbit"
74                 print " ul rate " int(maxrate[i]) "kbit"
75         }
76
77         # leaf qdisc
78         avpkt = 1200
79         for (i = 1; i <= n; i++) {
80                 ql = int((avgrate[i] + linespeed) * 1024 / (8 * pktsize[i]))
81                 printf "tc qdisc add dev "device" parent 1:"class[i]"0 handle "class[i]"00: "
82                 if (rtm1[i] > 0) {
83                         # rt class - use sfq
84                         print "sfq perturb 2 limit " ql
85                 } else {
86                         # non-rt class - use red
87                         min = int(maxrate[i] * 1024 / 8 * 0.05)
88                         if (min < avpkt) min = avpkt
89                         dqb = 8 * min;
90                         max = int(2.1*min)
91                         rburst = int((2*min + max) / (3 * avpkt))
92                         if (rburst < 2) rburst = 2
93                         print "red min " min " max " max " burst " rburst " avpkt " avpkt " limit " dqb " probability 0.04 ecn"
94                 }
95         }
96         
97         # filter rule
98         for (i = 1; i <= n; i++) {
99                 print "tc filter add dev "device" parent 1: prio "class[i]" protocol ip handle "class[i]" fw flowid 1:"class[i] "0" 
100         }
101 }
102