]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/tc/fq.c
tree-wide: use ASSERT_PTR more
[thirdparty/systemd.git] / src / network / tc / fq.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later
7234b915
SS
2 * Copyright © 2019 VMware, Inc. */
3
4#include <linux/pkt_sched.h>
5
6#include "alloc-util.h"
7#include "conf-parser.h"
8#include "fq.h"
9#include "netlink-util.h"
10#include "parse-util.h"
11#include "string-util.h"
c03ef420 12#include "strv.h"
e83562e5 13
949fb07e 14static int fair_queueing_init(QDisc *qdisc) {
ca58d00c 15 FairQueueing *fq;
e83562e5
YW
16
17 assert(qdisc);
18
19 fq = FQ(qdisc);
20
21 fq->pacing = -1;
22 fq->ce_threshold_usec = USEC_INFINITY;
23
24 return 0;
25}
7234b915 26
949fb07e 27static int fair_queueing_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req) {
ca58d00c 28 FairQueueing *fq;
7234b915
SS
29 int r;
30
31 assert(link);
32 assert(qdisc);
33 assert(req);
34
16924f54 35 assert_se(fq = FQ(qdisc));
7234b915
SS
36
37 r = sd_netlink_message_open_container_union(req, TCA_OPTIONS, "fq");
38 if (r < 0)
16924f54 39 return r;
7234b915 40
e83562e5
YW
41 if (fq->packet_limit > 0) {
42 r = sd_netlink_message_append_u32(req, TCA_FQ_PLIMIT, fq->packet_limit);
43 if (r < 0)
16924f54 44 return r;
e83562e5
YW
45 }
46
47 if (fq->flow_limit > 0) {
48 r = sd_netlink_message_append_u32(req, TCA_FQ_FLOW_PLIMIT, fq->flow_limit);
49 if (r < 0)
16924f54 50 return r;
e83562e5
YW
51 }
52
53 if (fq->quantum > 0) {
54 r = sd_netlink_message_append_u32(req, TCA_FQ_QUANTUM, fq->quantum);
55 if (r < 0)
16924f54 56 return r;
e83562e5
YW
57 }
58
59 if (fq->initial_quantum > 0) {
60 r = sd_netlink_message_append_u32(req, TCA_FQ_INITIAL_QUANTUM, fq->initial_quantum);
61 if (r < 0)
16924f54 62 return r;
e83562e5
YW
63 }
64
65 if (fq->pacing >= 0) {
66 r = sd_netlink_message_append_u32(req, TCA_FQ_RATE_ENABLE, fq->pacing);
67 if (r < 0)
16924f54 68 return r;
e83562e5
YW
69 }
70
71 if (fq->max_rate > 0) {
72 r = sd_netlink_message_append_u32(req, TCA_FQ_FLOW_MAX_RATE, fq->max_rate);
73 if (r < 0)
16924f54 74 return r;
e83562e5
YW
75 }
76
77 if (fq->buckets > 0) {
78 uint32_t l;
79
80 l = log2u(fq->buckets);
81 r = sd_netlink_message_append_u32(req, TCA_FQ_BUCKETS_LOG, l);
82 if (r < 0)
16924f54 83 return r;
e83562e5
YW
84 }
85
86 if (fq->orphan_mask > 0) {
87 r = sd_netlink_message_append_u32(req, TCA_FQ_ORPHAN_MASK, fq->orphan_mask);
88 if (r < 0)
16924f54 89 return r;
e83562e5
YW
90 }
91
92 if (fq->ce_threshold_usec != USEC_INFINITY) {
93 r = sd_netlink_message_append_u32(req, TCA_FQ_CE_THRESHOLD, fq->ce_threshold_usec);
94 if (r < 0)
16924f54 95 return r;
e83562e5 96 }
7234b915
SS
97
98 r = sd_netlink_message_close_container(req);
99 if (r < 0)
16924f54 100 return r;
7234b915
SS
101
102 return 0;
103}
104
949fb07e 105int config_parse_fair_queueing_u32(
7234b915
SS
106 const char *unit,
107 const char *filename,
108 unsigned line,
109 const char *section,
110 unsigned section_line,
111 const char *lvalue,
112 int ltype,
113 const char *rvalue,
114 void *data,
115 void *userdata) {
116
117 _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
ca58d00c 118 FairQueueing *fq;
99534007 119 Network *network = ASSERT_PTR(data);
e83562e5 120 uint32_t *p;
7234b915
SS
121 int r;
122
123 assert(filename);
124 assert(lvalue);
125 assert(rvalue);
7234b915
SS
126
127 r = qdisc_new_static(QDISC_KIND_FQ, network, filename, section_line, &qdisc);
128 if (r == -ENOMEM)
129 return log_oom();
d96edb2c
YW
130 if (r < 0) {
131 log_syntax(unit, LOG_WARNING, filename, line, r,
132 "More than one kind of queueing discipline, ignoring assignment: %m");
133 return 0;
134 }
7234b915
SS
135
136 fq = FQ(qdisc);
137
18de0969 138 if (streq(lvalue, "PacketLimit"))
e83562e5 139 p = &fq->packet_limit;
18de0969 140 else if (streq(lvalue, "FlowLimit"))
e83562e5 141 p = &fq->flow_limit;
18de0969 142 else if (streq(lvalue, "Buckets"))
e83562e5 143 p = &fq->buckets;
18de0969 144 else if (streq(lvalue, "OrphanMask"))
e83562e5
YW
145 p = &fq->orphan_mask;
146 else
04499a70 147 assert_not_reached();
e83562e5 148
7234b915 149 if (isempty(rvalue)) {
e83562e5 150 *p = 0;
7234b915
SS
151
152 qdisc = NULL;
153 return 0;
154 }
155
e83562e5 156 r = safe_atou32(rvalue, p);
7234b915 157 if (r < 0) {
d96edb2c 158 log_syntax(unit, LOG_WARNING, filename, line, r,
7234b915
SS
159 "Failed to parse '%s=', ignoring assignment: %s",
160 lvalue, rvalue);
161 return 0;
162 }
163
164 qdisc = NULL;
165
166 return 0;
167}
168
949fb07e 169int config_parse_fair_queueing_size(
e83562e5
YW
170 const char *unit,
171 const char *filename,
172 unsigned line,
173 const char *section,
174 unsigned section_line,
175 const char *lvalue,
176 int ltype,
177 const char *rvalue,
178 void *data,
179 void *userdata) {
180
181 _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
ca58d00c 182 FairQueueing *fq;
99534007 183 Network *network = ASSERT_PTR(data);
e83562e5
YW
184 uint64_t sz;
185 uint32_t *p;
186 int r;
187
188 assert(filename);
189 assert(lvalue);
190 assert(rvalue);
e83562e5
YW
191
192 r = qdisc_new_static(QDISC_KIND_FQ, network, filename, section_line, &qdisc);
193 if (r == -ENOMEM)
194 return log_oom();
d96edb2c
YW
195 if (r < 0) {
196 log_syntax(unit, LOG_WARNING, filename, line, r,
197 "More than one kind of queueing discipline, ignoring assignment: %m");
198 return 0;
199 }
e83562e5
YW
200
201 fq = FQ(qdisc);
202
c03ef420 203 if (STR_IN_SET(lvalue, "QuantumBytes", "Quantum"))
e83562e5 204 p = &fq->quantum;
c03ef420 205 else if (STR_IN_SET(lvalue, "InitialQuantumBytes", "InitialQuantum"))
e83562e5
YW
206 p = &fq->initial_quantum;
207 else
04499a70 208 assert_not_reached();
e83562e5
YW
209
210 if (isempty(rvalue)) {
211 *p = 0;
212
213 qdisc = NULL;
214 return 0;
215 }
216
217 r = parse_size(rvalue, 1024, &sz);
218 if (r < 0) {
d96edb2c 219 log_syntax(unit, LOG_WARNING, filename, line, r,
e83562e5
YW
220 "Failed to parse '%s=', ignoring assignment: %s",
221 lvalue, rvalue);
222 return 0;
223 }
224 if (sz > UINT32_MAX) {
d96edb2c 225 log_syntax(unit, LOG_WARNING, filename, line, 0,
e83562e5
YW
226 "Specified '%s=' is too large, ignoring assignment: %s",
227 lvalue, rvalue);
228 return 0;
229 }
230
231 *p = sz;
232 qdisc = NULL;
233
234 return 0;
235}
236
949fb07e 237int config_parse_fair_queueing_bool(
e83562e5
YW
238 const char *unit,
239 const char *filename,
240 unsigned line,
241 const char *section,
242 unsigned section_line,
243 const char *lvalue,
244 int ltype,
245 const char *rvalue,
246 void *data,
247 void *userdata) {
248
249 _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
ca58d00c 250 FairQueueing *fq;
99534007 251 Network *network = ASSERT_PTR(data);
e83562e5
YW
252 int r;
253
254 assert(filename);
255 assert(lvalue);
256 assert(rvalue);
e83562e5
YW
257
258 r = qdisc_new_static(QDISC_KIND_FQ, network, filename, section_line, &qdisc);
259 if (r == -ENOMEM)
260 return log_oom();
d96edb2c
YW
261 if (r < 0) {
262 log_syntax(unit, LOG_WARNING, filename, line, r,
263 "More than one kind of queueing discipline, ignoring assignment: %m");
264 return 0;
265 }
e83562e5
YW
266
267 fq = FQ(qdisc);
268
269 if (isempty(rvalue)) {
270 fq->pacing = -1;
271
272 qdisc = NULL;
273 return 0;
274 }
275
276 r = parse_boolean(rvalue);
277 if (r < 0) {
d96edb2c 278 log_syntax(unit, LOG_WARNING, filename, line, r,
e83562e5
YW
279 "Failed to parse '%s=', ignoring assignment: %s",
280 lvalue, rvalue);
281 return 0;
282 }
283
284 fq->pacing = r;
285 qdisc = NULL;
286
287 return 0;
288}
289
949fb07e 290int config_parse_fair_queueing_usec(
e83562e5
YW
291 const char *unit,
292 const char *filename,
293 unsigned line,
294 const char *section,
295 unsigned section_line,
296 const char *lvalue,
297 int ltype,
298 const char *rvalue,
299 void *data,
300 void *userdata) {
301
302 _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
ca58d00c 303 FairQueueing *fq;
99534007 304 Network *network = ASSERT_PTR(data);
e83562e5
YW
305 usec_t sec;
306 int r;
307
308 assert(filename);
309 assert(lvalue);
310 assert(rvalue);
e83562e5
YW
311
312 r = qdisc_new_static(QDISC_KIND_FQ, network, filename, section_line, &qdisc);
313 if (r == -ENOMEM)
314 return log_oom();
d96edb2c
YW
315 if (r < 0) {
316 log_syntax(unit, LOG_WARNING, filename, line, r,
317 "More than one kind of queueing discipline, ignoring assignment: %m");
318 return 0;
319 }
e83562e5
YW
320
321 fq = FQ(qdisc);
322
323 if (isempty(rvalue)) {
324 fq->ce_threshold_usec = USEC_INFINITY;
325
326 qdisc = NULL;
327 return 0;
328 }
329
330 r = parse_sec(rvalue, &sec);
331 if (r < 0) {
d96edb2c 332 log_syntax(unit, LOG_WARNING, filename, line, r,
e83562e5
YW
333 "Failed to parse '%s=', ignoring assignment: %s",
334 lvalue, rvalue);
335 return 0;
336 }
337 if (sec > UINT32_MAX) {
d96edb2c 338 log_syntax(unit, LOG_WARNING, filename, line, 0,
e83562e5
YW
339 "Specified '%s=' is too large, ignoring assignment: %s",
340 lvalue, rvalue);
341 return 0;
342 }
343
344 fq->ce_threshold_usec = sec;
345 qdisc = NULL;
346
347 return 0;
348}
349
949fb07e 350int config_parse_fair_queueing_max_rate(
e83562e5
YW
351 const char *unit,
352 const char *filename,
353 unsigned line,
354 const char *section,
355 unsigned section_line,
356 const char *lvalue,
357 int ltype,
358 const char *rvalue,
359 void *data,
360 void *userdata) {
361
362 _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
ca58d00c 363 FairQueueing *fq;
99534007 364 Network *network = ASSERT_PTR(data);
e83562e5
YW
365 uint64_t sz;
366 int r;
367
368 assert(filename);
369 assert(lvalue);
370 assert(rvalue);
e83562e5
YW
371
372 r = qdisc_new_static(QDISC_KIND_FQ, network, filename, section_line, &qdisc);
373 if (r == -ENOMEM)
374 return log_oom();
d96edb2c
YW
375 if (r < 0) {
376 log_syntax(unit, LOG_WARNING, filename, line, r,
377 "More than one kind of queueing discipline, ignoring assignment: %m");
378 return 0;
379 }
e83562e5
YW
380
381 fq = FQ(qdisc);
382
383 if (isempty(rvalue)) {
384 fq->max_rate = 0;
385
386 qdisc = NULL;
387 return 0;
388 }
389
390 r = parse_size(rvalue, 1000, &sz);
391 if (r < 0) {
d96edb2c 392 log_syntax(unit, LOG_WARNING, filename, line, r,
e83562e5
YW
393 "Failed to parse '%s=', ignoring assignment: %s",
394 lvalue, rvalue);
395 return 0;
396 }
397 if (sz / 8 > UINT32_MAX) {
d96edb2c 398 log_syntax(unit, LOG_WARNING, filename, line, 0,
e83562e5
YW
399 "Specified '%s=' is too large, ignoring assignment: %s",
400 lvalue, rvalue);
401 return 0;
402 }
403
404 fq->max_rate = sz / 8;
405 qdisc = NULL;
406
407 return 0;
408}
409
7234b915 410const QDiscVTable fq_vtable = {
949fb07e 411 .init = fair_queueing_init,
ca58d00c 412 .object_size = sizeof(FairQueueing),
7234b915 413 .tca_kind = "fq",
949fb07e 414 .fill_message = fair_queueing_fill_message,
7234b915 415};