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>
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <arpa/inet.h>
28 static void explain(void)
31 "Usage: ... sfb [ rehash SECS ] [ db SECS ]\n"
32 " [ limit PACKETS ] [ max PACKETS ] [ target PACKETS ]\n"
33 " [ increment FLOAT ] [ decrement FLOAT ]\n"
34 " [ penalty_rate PPS ] [ penalty_burst PACKETS ]\n");
37 static int get_prob(__u32
*val
, const char *arg
)
44 d
= strtod(arg
, &ptr
);
45 if (!ptr
|| ptr
== arg
|| d
< 0.0 || d
> 1.0)
47 *val
= (__u32
)(d
* SFB_MAX_PROB
+ 0.5);
51 static int sfb_parse_opt(struct qdisc_util
*qu
, int argc
, char **argv
,
54 struct tc_sfb_qopt opt
;
57 memset(&opt
, 0, sizeof(opt
));
58 opt
.rehash_interval
= 600*1000;
59 opt
.warmup_time
= 60*1000;
60 opt
.penalty_rate
= 10;
61 opt
.penalty_burst
= 20;
62 opt
.increment
= (SFB_MAX_PROB
+ 1000) / 2000;
63 opt
.decrement
= (SFB_MAX_PROB
+ 10000) / 20000;
66 if (strcmp(*argv
, "rehash") == 0) {
68 if (get_u32(&opt
.rehash_interval
, *argv
, 0)) {
69 fprintf(stderr
, "Illegal \"rehash\"\n");
72 } else if (strcmp(*argv
, "db") == 0) {
74 if (get_u32(&opt
.warmup_time
, *argv
, 0)) {
75 fprintf(stderr
, "Illegal \"db\"\n");
78 } else if (strcmp(*argv
, "limit") == 0) {
80 if (get_u32(&opt
.limit
, *argv
, 0)) {
81 fprintf(stderr
, "Illegal \"limit\"\n");
84 } else if (strcmp(*argv
, "max") == 0) {
86 if (get_u32(&opt
.max
, *argv
, 0)) {
87 fprintf(stderr
, "Illegal \"max\"\n");
90 } else if (strcmp(*argv
, "target") == 0) {
92 if (get_u32(&opt
.bin_size
, *argv
, 0)) {
93 fprintf(stderr
, "Illegal \"target\"\n");
96 } else if (strcmp(*argv
, "increment") == 0) {
98 if (get_prob(&opt
.increment
, *argv
)) {
99 fprintf(stderr
, "Illegal \"increment\"\n");
102 } else if (strcmp(*argv
, "decrement") == 0) {
104 if (get_prob(&opt
.decrement
, *argv
)) {
105 fprintf(stderr
, "Illegal \"decrement\"\n");
108 } else if (strcmp(*argv
, "penalty_rate") == 0) {
110 if (get_u32(&opt
.penalty_rate
, *argv
, 0)) {
111 fprintf(stderr
, "Illegal \"penalty_rate\"\n");
114 } else if (strcmp(*argv
, "penalty_burst") == 0) {
116 if (get_u32(&opt
.penalty_burst
, *argv
, 0)) {
117 fprintf(stderr
, "Illegal \"penalty_burst\"\n");
121 fprintf(stderr
, "What is \"%s\"?\n", *argv
);
129 if (opt
.bin_size
>= 1)
130 opt
.max
= (opt
.bin_size
* 5 + 1) / 4;
134 if (opt
.bin_size
== 0)
135 opt
.bin_size
= (opt
.max
* 4 + 3) / 5;
137 tail
= NLMSG_TAIL(n
);
138 addattr_l(n
, 1024, TCA_OPTIONS
, NULL
, 0);
139 addattr_l(n
, 1024, TCA_SFB_PARMS
, &opt
, sizeof(opt
));
140 tail
->rta_len
= (void *) NLMSG_TAIL(n
) - (void *) tail
;
144 static int sfb_print_opt(struct qdisc_util
*qu
, FILE *f
, struct rtattr
*opt
)
146 struct rtattr
*tb
[__TCA_SFB_MAX
];
147 struct tc_sfb_qopt
*qopt
;
152 parse_rtattr_nested(tb
, TCA_SFB_MAX
, opt
);
153 if (tb
[TCA_SFB_PARMS
] == NULL
)
155 qopt
= RTA_DATA(tb
[TCA_SFB_PARMS
]);
156 if (RTA_PAYLOAD(tb
[TCA_SFB_PARMS
]) < sizeof(*qopt
))
160 "limit %d max %d target %d\n"
161 " increment %.5f decrement %.5f penalty rate %d burst %d "
163 qopt
->limit
, qopt
->max
, qopt
->bin_size
,
164 (double)qopt
->increment
/ SFB_MAX_PROB
,
165 (double)qopt
->decrement
/ SFB_MAX_PROB
,
166 qopt
->penalty_rate
, qopt
->penalty_burst
,
167 qopt
->rehash_interval
, qopt
->warmup_time
);
172 static int sfb_print_xstats(struct qdisc_util
*qu
, FILE *f
,
173 struct rtattr
*xstats
)
175 struct tc_sfb_xstats
*st
;
180 if (RTA_PAYLOAD(xstats
) < sizeof(*st
))
183 st
= RTA_DATA(xstats
);
185 " earlydrop %u penaltydrop %u bucketdrop %u queuedrop %u childdrop %u marked %u\n"
186 " maxqlen %u maxprob %.5f avgprob %.5f ",
187 st
->earlydrop
, st
->penaltydrop
, st
->bucketdrop
, st
->queuedrop
, st
->childdrop
,
189 st
->maxqlen
, (double)st
->maxprob
/ SFB_MAX_PROB
,
190 (double)st
->avgprob
/ SFB_MAX_PROB
);
195 struct qdisc_util sfb_qdisc_util
= {
197 .parse_qopt
= sfb_parse_opt
,
198 .print_qopt
= sfb_print_opt
,
199 .print_xstats
= sfb_print_xstats
,