]>
Commit | Line | Data |
---|---|---|
6054c1eb | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
ac74bd2a TL |
2 | /* q_hhf.c Heavy-Hitter Filter (HHF) |
3 | * | |
4 | * Copyright (C) 2013 Terry Lam <vtlam@google.com> | |
5 | */ | |
6 | #include <stdio.h> | |
7 | #include <stdlib.h> | |
8 | #include <unistd.h> | |
ac74bd2a TL |
9 | #include <fcntl.h> |
10 | #include <sys/socket.h> | |
11 | #include <netinet/in.h> | |
12 | #include <arpa/inet.h> | |
13 | #include <string.h> | |
14 | ||
15 | #include "utils.h" | |
16 | #include "tc_util.h" | |
17 | ||
18 | static void explain(void) | |
19 | { | |
8589eb4e MC |
20 | fprintf(stderr, |
21 | "Usage: ... hhf [ limit PACKETS ] [ quantum BYTES]\n" | |
22 | " [ hh_limit NUMBER ]\n" | |
23 | " [ reset_timeout TIME ]\n" | |
24 | " [ admit_bytes BYTES ]\n" | |
25 | " [ evict_timeout TIME ]\n" | |
26 | " [ non_hh_weight NUMBER ]\n"); | |
ac74bd2a TL |
27 | } |
28 | ||
29 | static int hhf_parse_opt(struct qdisc_util *qu, int argc, char **argv, | |
927e3cfb | 30 | struct nlmsghdr *n, const char *dev) |
ac74bd2a | 31 | { |
32a121cb SH |
32 | unsigned int limit = 0; |
33 | unsigned int quantum = 0; | |
34 | unsigned int hh_limit = 0; | |
35 | unsigned int reset_timeout = 0; | |
36 | unsigned int admit_bytes = 0; | |
37 | unsigned int evict_timeout = 0; | |
38 | unsigned int non_hh_weight = 0; | |
ac74bd2a TL |
39 | struct rtattr *tail; |
40 | ||
41 | while (argc > 0) { | |
42 | if (strcmp(*argv, "limit") == 0) { | |
43 | NEXT_ARG(); | |
44 | if (get_unsigned(&limit, *argv, 0)) { | |
45 | fprintf(stderr, "Illegal \"limit\"\n"); | |
46 | return -1; | |
47 | } | |
48 | } else if (strcmp(*argv, "quantum") == 0) { | |
49 | NEXT_ARG(); | |
50 | if (get_unsigned(&quantum, *argv, 0)) { | |
51 | fprintf(stderr, "Illegal \"quantum\"\n"); | |
52 | return -1; | |
53 | } | |
54 | } else if (strcmp(*argv, "hh_limit") == 0) { | |
55 | NEXT_ARG(); | |
56 | if (get_unsigned(&hh_limit, *argv, 0)) { | |
57 | fprintf(stderr, "Illegal \"hh_limit\"\n"); | |
58 | return -1; | |
59 | } | |
60 | } else if (strcmp(*argv, "reset_timeout") == 0) { | |
61 | NEXT_ARG(); | |
62 | if (get_time(&reset_timeout, *argv)) { | |
63 | fprintf(stderr, "Illegal \"reset_timeout\"\n"); | |
64 | return -1; | |
65 | } | |
66 | } else if (strcmp(*argv, "admit_bytes") == 0) { | |
67 | NEXT_ARG(); | |
68 | if (get_unsigned(&admit_bytes, *argv, 0)) { | |
69 | fprintf(stderr, "Illegal \"admit_bytes\"\n"); | |
70 | return -1; | |
71 | } | |
72 | } else if (strcmp(*argv, "evict_timeout") == 0) { | |
73 | NEXT_ARG(); | |
74 | if (get_time(&evict_timeout, *argv)) { | |
75 | fprintf(stderr, "Illegal \"evict_timeout\"\n"); | |
76 | return -1; | |
77 | } | |
78 | } else if (strcmp(*argv, "non_hh_weight") == 0) { | |
79 | NEXT_ARG(); | |
80 | if (get_unsigned(&non_hh_weight, *argv, 0)) { | |
81 | fprintf(stderr, "Illegal \"non_hh_weight\"\n"); | |
82 | return -1; | |
83 | } | |
84 | } else if (strcmp(*argv, "help") == 0) { | |
85 | explain(); | |
86 | return -1; | |
87 | } else { | |
88 | fprintf(stderr, "What is \"%s\"?\n", *argv); | |
89 | explain(); | |
90 | return -1; | |
91 | } | |
92 | argc--; argv++; | |
93 | } | |
94 | ||
c14f9d92 | 95 | tail = addattr_nest(n, 1024, TCA_OPTIONS); |
ac74bd2a TL |
96 | if (limit) |
97 | addattr_l(n, 1024, TCA_HHF_BACKLOG_LIMIT, &limit, | |
98 | sizeof(limit)); | |
99 | if (quantum) | |
100 | addattr_l(n, 1024, TCA_HHF_QUANTUM, &quantum, sizeof(quantum)); | |
101 | if (hh_limit) | |
102 | addattr_l(n, 1024, TCA_HHF_HH_FLOWS_LIMIT, &hh_limit, | |
103 | sizeof(hh_limit)); | |
104 | if (reset_timeout) | |
105 | addattr_l(n, 1024, TCA_HHF_RESET_TIMEOUT, &reset_timeout, | |
106 | sizeof(reset_timeout)); | |
107 | if (admit_bytes) | |
108 | addattr_l(n, 1024, TCA_HHF_ADMIT_BYTES, &admit_bytes, | |
109 | sizeof(admit_bytes)); | |
110 | if (evict_timeout) | |
111 | addattr_l(n, 1024, TCA_HHF_EVICT_TIMEOUT, &evict_timeout, | |
112 | sizeof(evict_timeout)); | |
113 | if (non_hh_weight) | |
114 | addattr_l(n, 1024, TCA_HHF_NON_HH_WEIGHT, &non_hh_weight, | |
115 | sizeof(non_hh_weight)); | |
c14f9d92 | 116 | addattr_nest_end(n, tail); |
ac74bd2a TL |
117 | return 0; |
118 | } | |
119 | ||
120 | static int hhf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) | |
121 | { | |
122 | struct rtattr *tb[TCA_HHF_MAX + 1]; | |
32a121cb SH |
123 | unsigned int limit; |
124 | unsigned int quantum; | |
125 | unsigned int hh_limit; | |
126 | unsigned int reset_timeout; | |
127 | unsigned int admit_bytes; | |
128 | unsigned int evict_timeout; | |
129 | unsigned int non_hh_weight; | |
130 | ||
ac74bd2a TL |
131 | SPRINT_BUF(b1); |
132 | ||
133 | if (opt == NULL) | |
134 | return 0; | |
135 | ||
136 | parse_rtattr_nested(tb, TCA_HHF_MAX, opt); | |
137 | ||
138 | if (tb[TCA_HHF_BACKLOG_LIMIT] && | |
139 | RTA_PAYLOAD(tb[TCA_HHF_BACKLOG_LIMIT]) >= sizeof(__u32)) { | |
140 | limit = rta_getattr_u32(tb[TCA_HHF_BACKLOG_LIMIT]); | |
f6564ed6 | 141 | print_uint(PRINT_ANY, "limit", "limit %up ", limit); |
ac74bd2a TL |
142 | } |
143 | if (tb[TCA_HHF_QUANTUM] && | |
144 | RTA_PAYLOAD(tb[TCA_HHF_QUANTUM]) >= sizeof(__u32)) { | |
145 | quantum = rta_getattr_u32(tb[TCA_HHF_QUANTUM]); | |
adbe5de9 | 146 | print_size(PRINT_ANY, "quantum", "quantum %s ", quantum); |
ac74bd2a TL |
147 | } |
148 | if (tb[TCA_HHF_HH_FLOWS_LIMIT] && | |
149 | RTA_PAYLOAD(tb[TCA_HHF_HH_FLOWS_LIMIT]) >= sizeof(__u32)) { | |
150 | hh_limit = rta_getattr_u32(tb[TCA_HHF_HH_FLOWS_LIMIT]); | |
f6564ed6 | 151 | print_uint(PRINT_ANY, "hh_limit", "hh_limit %u ", hh_limit); |
ac74bd2a TL |
152 | } |
153 | if (tb[TCA_HHF_RESET_TIMEOUT] && | |
154 | RTA_PAYLOAD(tb[TCA_HHF_RESET_TIMEOUT]) >= sizeof(__u32)) { | |
155 | reset_timeout = rta_getattr_u32(tb[TCA_HHF_RESET_TIMEOUT]); | |
f6564ed6 LM |
156 | print_uint(PRINT_JSON, "reset_timeout", NULL, reset_timeout); |
157 | print_string(PRINT_FP, NULL, "reset_timeout %s ", | |
158 | sprint_time(reset_timeout, b1)); | |
ac74bd2a TL |
159 | } |
160 | if (tb[TCA_HHF_ADMIT_BYTES] && | |
161 | RTA_PAYLOAD(tb[TCA_HHF_ADMIT_BYTES]) >= sizeof(__u32)) { | |
162 | admit_bytes = rta_getattr_u32(tb[TCA_HHF_ADMIT_BYTES]); | |
adbe5de9 PM |
163 | print_size(PRINT_ANY, "admit_bytes", "admit_bytes %s ", |
164 | admit_bytes); | |
ac74bd2a TL |
165 | } |
166 | if (tb[TCA_HHF_EVICT_TIMEOUT] && | |
167 | RTA_PAYLOAD(tb[TCA_HHF_EVICT_TIMEOUT]) >= sizeof(__u32)) { | |
168 | evict_timeout = rta_getattr_u32(tb[TCA_HHF_EVICT_TIMEOUT]); | |
f6564ed6 LM |
169 | print_uint(PRINT_JSON, "evict_timeout", NULL, evict_timeout); |
170 | print_string(PRINT_FP, NULL, "evict_timeout %s ", | |
171 | sprint_time(evict_timeout, b1)); | |
ac74bd2a TL |
172 | } |
173 | if (tb[TCA_HHF_NON_HH_WEIGHT] && | |
174 | RTA_PAYLOAD(tb[TCA_HHF_NON_HH_WEIGHT]) >= sizeof(__u32)) { | |
175 | non_hh_weight = rta_getattr_u32(tb[TCA_HHF_NON_HH_WEIGHT]); | |
f6564ed6 LM |
176 | print_uint(PRINT_ANY, "non_hh_weight", "non_hh_weight %u ", |
177 | non_hh_weight); | |
ac74bd2a TL |
178 | } |
179 | return 0; | |
180 | } | |
181 | ||
182 | static int hhf_print_xstats(struct qdisc_util *qu, FILE *f, | |
183 | struct rtattr *xstats) | |
184 | { | |
185 | struct tc_hhf_xstats *st; | |
186 | ||
187 | if (xstats == NULL) | |
188 | return 0; | |
189 | ||
190 | if (RTA_PAYLOAD(xstats) < sizeof(*st)) | |
191 | return -1; | |
192 | ||
193 | st = RTA_DATA(xstats); | |
194 | ||
f6564ed6 LM |
195 | print_uint(PRINT_ANY, "drop_overlimit", " drop_overlimit %u", |
196 | st->drop_overlimit); | |
197 | print_uint(PRINT_ANY, "hh_overlimit", " hh_overlimit %u", | |
198 | st->hh_overlimit); | |
199 | print_uint(PRINT_ANY, "tot_hh", " tot_hh %u", st->hh_tot_count); | |
200 | print_uint(PRINT_ANY, "cur_hh", " cur_hh %u", st->hh_cur_count); | |
201 | ||
ac74bd2a TL |
202 | return 0; |
203 | } | |
204 | ||
205 | struct qdisc_util hhf_qdisc_util = { | |
206 | .id = "hhf", | |
207 | .parse_qopt = hhf_parse_opt, | |
208 | .print_qopt = hhf_print_opt, | |
209 | .print_xstats = hhf_print_xstats, | |
210 | }; |