1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* q_hhf.c Heavy-Hitter Filter (HHF)
4 * Copyright (C) 2013 Terry Lam <vtlam@google.com>
10 #include <sys/socket.h>
11 #include <netinet/in.h>
12 #include <arpa/inet.h>
18 static void explain(void)
20 fprintf(stderr
, "Usage: ... hhf [ limit PACKETS ] [ quantum BYTES]\n");
21 fprintf(stderr
, " [ hh_limit NUMBER ]\n");
22 fprintf(stderr
, " [ reset_timeout TIME ]\n");
23 fprintf(stderr
, " [ admit_bytes BYTES ]\n");
24 fprintf(stderr
, " [ evict_timeout TIME ]\n");
25 fprintf(stderr
, " [ non_hh_weight NUMBER ]\n");
28 static int hhf_parse_opt(struct qdisc_util
*qu
, int argc
, char **argv
,
29 struct nlmsghdr
*n
, const char *dev
)
31 unsigned int limit
= 0;
32 unsigned int quantum
= 0;
33 unsigned int hh_limit
= 0;
34 unsigned int reset_timeout
= 0;
35 unsigned int admit_bytes
= 0;
36 unsigned int evict_timeout
= 0;
37 unsigned int non_hh_weight
= 0;
41 if (strcmp(*argv
, "limit") == 0) {
43 if (get_unsigned(&limit
, *argv
, 0)) {
44 fprintf(stderr
, "Illegal \"limit\"\n");
47 } else if (strcmp(*argv
, "quantum") == 0) {
49 if (get_unsigned(&quantum
, *argv
, 0)) {
50 fprintf(stderr
, "Illegal \"quantum\"\n");
53 } else if (strcmp(*argv
, "hh_limit") == 0) {
55 if (get_unsigned(&hh_limit
, *argv
, 0)) {
56 fprintf(stderr
, "Illegal \"hh_limit\"\n");
59 } else if (strcmp(*argv
, "reset_timeout") == 0) {
61 if (get_time(&reset_timeout
, *argv
)) {
62 fprintf(stderr
, "Illegal \"reset_timeout\"\n");
65 } else if (strcmp(*argv
, "admit_bytes") == 0) {
67 if (get_unsigned(&admit_bytes
, *argv
, 0)) {
68 fprintf(stderr
, "Illegal \"admit_bytes\"\n");
71 } else if (strcmp(*argv
, "evict_timeout") == 0) {
73 if (get_time(&evict_timeout
, *argv
)) {
74 fprintf(stderr
, "Illegal \"evict_timeout\"\n");
77 } else if (strcmp(*argv
, "non_hh_weight") == 0) {
79 if (get_unsigned(&non_hh_weight
, *argv
, 0)) {
80 fprintf(stderr
, "Illegal \"non_hh_weight\"\n");
83 } else if (strcmp(*argv
, "help") == 0) {
87 fprintf(stderr
, "What is \"%s\"?\n", *argv
);
94 tail
= addattr_nest(n
, 1024, TCA_OPTIONS
);
96 addattr_l(n
, 1024, TCA_HHF_BACKLOG_LIMIT
, &limit
,
99 addattr_l(n
, 1024, TCA_HHF_QUANTUM
, &quantum
, sizeof(quantum
));
101 addattr_l(n
, 1024, TCA_HHF_HH_FLOWS_LIMIT
, &hh_limit
,
104 addattr_l(n
, 1024, TCA_HHF_RESET_TIMEOUT
, &reset_timeout
,
105 sizeof(reset_timeout
));
107 addattr_l(n
, 1024, TCA_HHF_ADMIT_BYTES
, &admit_bytes
,
108 sizeof(admit_bytes
));
110 addattr_l(n
, 1024, TCA_HHF_EVICT_TIMEOUT
, &evict_timeout
,
111 sizeof(evict_timeout
));
113 addattr_l(n
, 1024, TCA_HHF_NON_HH_WEIGHT
, &non_hh_weight
,
114 sizeof(non_hh_weight
));
115 addattr_nest_end(n
, tail
);
119 static int hhf_print_opt(struct qdisc_util
*qu
, FILE *f
, struct rtattr
*opt
)
121 struct rtattr
*tb
[TCA_HHF_MAX
+ 1];
123 unsigned int quantum
;
124 unsigned int hh_limit
;
125 unsigned int reset_timeout
;
126 unsigned int admit_bytes
;
127 unsigned int evict_timeout
;
128 unsigned int non_hh_weight
;
135 parse_rtattr_nested(tb
, TCA_HHF_MAX
, opt
);
137 if (tb
[TCA_HHF_BACKLOG_LIMIT
] &&
138 RTA_PAYLOAD(tb
[TCA_HHF_BACKLOG_LIMIT
]) >= sizeof(__u32
)) {
139 limit
= rta_getattr_u32(tb
[TCA_HHF_BACKLOG_LIMIT
]);
140 fprintf(f
, "limit %up ", limit
);
142 if (tb
[TCA_HHF_QUANTUM
] &&
143 RTA_PAYLOAD(tb
[TCA_HHF_QUANTUM
]) >= sizeof(__u32
)) {
144 quantum
= rta_getattr_u32(tb
[TCA_HHF_QUANTUM
]);
145 fprintf(f
, "quantum %u ", quantum
);
147 if (tb
[TCA_HHF_HH_FLOWS_LIMIT
] &&
148 RTA_PAYLOAD(tb
[TCA_HHF_HH_FLOWS_LIMIT
]) >= sizeof(__u32
)) {
149 hh_limit
= rta_getattr_u32(tb
[TCA_HHF_HH_FLOWS_LIMIT
]);
150 fprintf(f
, "hh_limit %u ", hh_limit
);
152 if (tb
[TCA_HHF_RESET_TIMEOUT
] &&
153 RTA_PAYLOAD(tb
[TCA_HHF_RESET_TIMEOUT
]) >= sizeof(__u32
)) {
154 reset_timeout
= rta_getattr_u32(tb
[TCA_HHF_RESET_TIMEOUT
]);
155 fprintf(f
, "reset_timeout %s ", sprint_time(reset_timeout
, b1
));
157 if (tb
[TCA_HHF_ADMIT_BYTES
] &&
158 RTA_PAYLOAD(tb
[TCA_HHF_ADMIT_BYTES
]) >= sizeof(__u32
)) {
159 admit_bytes
= rta_getattr_u32(tb
[TCA_HHF_ADMIT_BYTES
]);
160 fprintf(f
, "admit_bytes %u ", admit_bytes
);
162 if (tb
[TCA_HHF_EVICT_TIMEOUT
] &&
163 RTA_PAYLOAD(tb
[TCA_HHF_EVICT_TIMEOUT
]) >= sizeof(__u32
)) {
164 evict_timeout
= rta_getattr_u32(tb
[TCA_HHF_EVICT_TIMEOUT
]);
165 fprintf(f
, "evict_timeout %s ", sprint_time(evict_timeout
, b1
));
167 if (tb
[TCA_HHF_NON_HH_WEIGHT
] &&
168 RTA_PAYLOAD(tb
[TCA_HHF_NON_HH_WEIGHT
]) >= sizeof(__u32
)) {
169 non_hh_weight
= rta_getattr_u32(tb
[TCA_HHF_NON_HH_WEIGHT
]);
170 fprintf(f
, "non_hh_weight %u ", non_hh_weight
);
175 static int hhf_print_xstats(struct qdisc_util
*qu
, FILE *f
,
176 struct rtattr
*xstats
)
178 struct tc_hhf_xstats
*st
;
183 if (RTA_PAYLOAD(xstats
) < sizeof(*st
))
186 st
= RTA_DATA(xstats
);
188 fprintf(f
, " drop_overlimit %u hh_overlimit %u tot_hh %u cur_hh %u",
189 st
->drop_overlimit
, st
->hh_overlimit
,
190 st
->hh_tot_count
, st
->hh_cur_count
);
194 struct qdisc_util hhf_qdisc_util
= {
196 .parse_qopt
= hhf_parse_opt
,
197 .print_qopt
= hhf_print_opt
,
198 .print_xstats
= hhf_print_xstats
,