2 * q_sfb.c Stochastic Fair Blue.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Juliusz Chroboczek <jch@pps.jussieu.fr>
19 #include <sys/socket.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
27 static void explain(void)
30 "Usage: ... sfb [ rehash SECS ] [ db SECS ]\n"
31 " [ limit PACKETS ] [ max PACKETS ] [ target PACKETS ]\n"
32 " [ increment FLOAT ] [ decrement FLOAT ]\n"
33 " [ penalty_rate PPS ] [ penalty_burst PACKETS ]\n");
36 static int get_prob(__u32
*val
, const char *arg
)
43 d
= strtod(arg
, &ptr
);
44 if (!ptr
|| ptr
== arg
|| d
< 0.0 || d
> 1.0)
46 *val
= (__u32
)(d
* SFB_MAX_PROB
+ 0.5);
50 static int sfb_parse_opt(struct qdisc_util
*qu
, int argc
, char **argv
,
51 struct nlmsghdr
*n
, const char *dev
)
53 struct tc_sfb_qopt opt
= {
54 .rehash_interval
= 600*1000,
55 .warmup_time
= 60*1000,
58 .increment
= (SFB_MAX_PROB
+ 1000) / 2000,
59 .decrement
= (SFB_MAX_PROB
+ 10000) / 20000,
64 if (strcmp(*argv
, "rehash") == 0) {
66 if (get_u32(&opt
.rehash_interval
, *argv
, 0)) {
67 fprintf(stderr
, "Illegal \"rehash\"\n");
70 } else if (strcmp(*argv
, "db") == 0) {
72 if (get_u32(&opt
.warmup_time
, *argv
, 0)) {
73 fprintf(stderr
, "Illegal \"db\"\n");
76 } else if (strcmp(*argv
, "limit") == 0) {
78 if (get_u32(&opt
.limit
, *argv
, 0)) {
79 fprintf(stderr
, "Illegal \"limit\"\n");
82 } else if (strcmp(*argv
, "max") == 0) {
84 if (get_u32(&opt
.max
, *argv
, 0)) {
85 fprintf(stderr
, "Illegal \"max\"\n");
88 } else if (strcmp(*argv
, "target") == 0) {
90 if (get_u32(&opt
.bin_size
, *argv
, 0)) {
91 fprintf(stderr
, "Illegal \"target\"\n");
94 } else if (strcmp(*argv
, "increment") == 0) {
96 if (get_prob(&opt
.increment
, *argv
)) {
97 fprintf(stderr
, "Illegal \"increment\"\n");
100 } else if (strcmp(*argv
, "decrement") == 0) {
102 if (get_prob(&opt
.decrement
, *argv
)) {
103 fprintf(stderr
, "Illegal \"decrement\"\n");
106 } else if (strcmp(*argv
, "penalty_rate") == 0) {
108 if (get_u32(&opt
.penalty_rate
, *argv
, 0)) {
109 fprintf(stderr
, "Illegal \"penalty_rate\"\n");
112 } else if (strcmp(*argv
, "penalty_burst") == 0) {
114 if (get_u32(&opt
.penalty_burst
, *argv
, 0)) {
115 fprintf(stderr
, "Illegal \"penalty_burst\"\n");
119 fprintf(stderr
, "What is \"%s\"?\n", *argv
);
127 if (opt
.bin_size
>= 1)
128 opt
.max
= (opt
.bin_size
* 5 + 1) / 4;
132 if (opt
.bin_size
== 0)
133 opt
.bin_size
= (opt
.max
* 4 + 3) / 5;
135 tail
= addattr_nest(n
, 1024, TCA_OPTIONS
);
136 addattr_l(n
, 1024, TCA_SFB_PARMS
, &opt
, sizeof(opt
));
137 addattr_nest_end(n
, tail
);
141 static int sfb_print_opt(struct qdisc_util
*qu
, FILE *f
, struct rtattr
*opt
)
143 struct rtattr
*tb
[__TCA_SFB_MAX
];
144 struct tc_sfb_qopt
*qopt
;
151 parse_rtattr_nested(tb
, TCA_SFB_MAX
, opt
);
152 if (tb
[TCA_SFB_PARMS
] == NULL
)
154 qopt
= RTA_DATA(tb
[TCA_SFB_PARMS
]);
155 if (RTA_PAYLOAD(tb
[TCA_SFB_PARMS
]) < sizeof(*qopt
))
158 print_uint(PRINT_JSON
, "rehash", NULL
, qopt
->rehash_interval
* 1000);
159 print_string(PRINT_FP
, NULL
, "rehash %s ",
160 sprint_time(qopt
->rehash_interval
* 1000, b1
));
162 print_uint(PRINT_JSON
, "db", NULL
, qopt
->warmup_time
* 1000);
163 print_string(PRINT_FP
, NULL
, "db %s ",
164 sprint_time(qopt
->warmup_time
* 1000, b1
));
166 print_uint(PRINT_ANY
, "limit", "limit %up ", qopt
->limit
);
167 print_uint(PRINT_ANY
, "max", "max %up ", qopt
->max
);
168 print_uint(PRINT_ANY
, "target", "target %up ", qopt
->bin_size
);
170 print_float(PRINT_ANY
, "increment", "increment %lg ",
171 (double)qopt
->increment
/ SFB_MAX_PROB
);
172 print_float(PRINT_ANY
, "decrement", "decrement %lg ",
173 (double)qopt
->decrement
/ SFB_MAX_PROB
);
175 print_uint(PRINT_ANY
, "penalty_rate", "penalty_rate %upps ",
177 print_uint(PRINT_ANY
, "penalty_burst", "penalty_burst %up ",
178 qopt
->penalty_burst
);
183 static int sfb_print_xstats(struct qdisc_util
*qu
, FILE *f
,
184 struct rtattr
*xstats
)
186 struct tc_sfb_xstats
*st
;
191 if (RTA_PAYLOAD(xstats
) < sizeof(*st
))
194 st
= RTA_DATA(xstats
);
196 print_uint(PRINT_ANY
, "earlydrop", " earlydrop %u", st
->earlydrop
);
197 print_uint(PRINT_ANY
, "penaltydrop", " penaltydrop %u",
199 print_uint(PRINT_ANY
, "bucketdrop", " bucketdrop %u", st
->bucketdrop
);
200 print_uint(PRINT_ANY
, "queuedrop", " queuedrop %u", st
->queuedrop
);
201 print_uint(PRINT_ANY
, "childdrop", " childdrop %u", st
->childdrop
);
202 print_uint(PRINT_ANY
, "marked", " marked %u", st
->marked
);
204 print_uint(PRINT_ANY
, "maxqlen", " maxqlen %u", st
->maxqlen
);
206 print_float(PRINT_ANY
, "maxprob", " maxprob %lg",
207 (double)st
->maxprob
/ SFB_MAX_PROB
);
208 print_float(PRINT_ANY
, "avgprob", " avgprob %lg",
209 (double)st
->avgprob
/ SFB_MAX_PROB
);
214 struct qdisc_util sfb_qdisc_util
= {
216 .parse_qopt
= sfb_parse_opt
,
217 .print_qopt
= sfb_print_opt
,
218 .print_xstats
= sfb_print_xstats
,