]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/tc/fq.c
network: tc: rename several settings which take size in bytes
[thirdparty/systemd.git] / src / network / tc / fq.c
CommitLineData
7234b915
SS
1/* SPDX-License-Identifier: LGPL-2.1+
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
35 fq = FQ(qdisc);
36
37 r = sd_netlink_message_open_container_union(req, TCA_OPTIONS, "fq");
38 if (r < 0)
39 return log_link_error_errno(link, r, "Could not open container TCA_OPTIONS: %m");
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)
44 return log_link_error_errno(link, r, "Could not append TCA_FQ_PLIMIT attribute: %m");
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)
50 return log_link_error_errno(link, r, "Could not append TCA_FQ_FLOW_PLIMIT attribute: %m");
51 }
52
53 if (fq->quantum > 0) {
54 r = sd_netlink_message_append_u32(req, TCA_FQ_QUANTUM, fq->quantum);
55 if (r < 0)
56 return log_link_error_errno(link, r, "Could not append TCA_FQ_QUANTUM attribute: %m");
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)
62 return log_link_error_errno(link, r, "Could not append TCA_FQ_INITIAL_QUANTUM attribute: %m");
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)
68 return log_link_error_errno(link, r, "Could not append TCA_FQ_RATE_ENABLE attribute: %m");
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)
74 return log_link_error_errno(link, r, "Could not append TCA_FQ_FLOW_MAX_RATE attribute: %m");
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)
83 return log_link_error_errno(link, r, "Could not append TCA_FQ_BUCKETS_LOG attribute: %m");
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)
89 return log_link_error_errno(link, r, "Could not append TCA_FQ_ORPHAN_MASK attribute: %m");
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)
95 return log_link_error_errno(link, r, "Could not append TCA_FQ_CE_THRESHOLD attribute: %m");
96 }
7234b915
SS
97
98 r = sd_netlink_message_close_container(req);
99 if (r < 0)
100 return log_link_error_errno(link, r, "Could not close container TCA_OPTIONS: %m");
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;
7234b915 119 Network *network = data;
e83562e5 120 uint32_t *p;
7234b915
SS
121 int r;
122
123 assert(filename);
124 assert(lvalue);
125 assert(rvalue);
126 assert(data);
127
128 r = qdisc_new_static(QDISC_KIND_FQ, network, filename, section_line, &qdisc);
129 if (r == -ENOMEM)
130 return log_oom();
131 if (r < 0)
132 return log_syntax(unit, LOG_ERR, filename, line, r,
133 "More than one kind of queueing discipline, ignoring assignment: %m");
134
135 fq = FQ(qdisc);
136
18de0969 137 if (streq(lvalue, "PacketLimit"))
e83562e5 138 p = &fq->packet_limit;
18de0969 139 else if (streq(lvalue, "FlowLimit"))
e83562e5 140 p = &fq->flow_limit;
18de0969 141 else if (streq(lvalue, "Buckets"))
e83562e5 142 p = &fq->buckets;
18de0969 143 else if (streq(lvalue, "OrphanMask"))
e83562e5
YW
144 p = &fq->orphan_mask;
145 else
146 assert_not_reached("Invalid lvalue");
147
7234b915 148 if (isempty(rvalue)) {
e83562e5 149 *p = 0;
7234b915
SS
150
151 qdisc = NULL;
152 return 0;
153 }
154
e83562e5 155 r = safe_atou32(rvalue, p);
7234b915
SS
156 if (r < 0) {
157 log_syntax(unit, LOG_ERR, filename, line, r,
158 "Failed to parse '%s=', ignoring assignment: %s",
159 lvalue, rvalue);
160 return 0;
161 }
162
163 qdisc = NULL;
164
165 return 0;
166}
167
949fb07e 168int config_parse_fair_queueing_size(
e83562e5
YW
169 const char *unit,
170 const char *filename,
171 unsigned line,
172 const char *section,
173 unsigned section_line,
174 const char *lvalue,
175 int ltype,
176 const char *rvalue,
177 void *data,
178 void *userdata) {
179
180 _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
ca58d00c 181 FairQueueing *fq;
e83562e5
YW
182 Network *network = data;
183 uint64_t sz;
184 uint32_t *p;
185 int r;
186
187 assert(filename);
188 assert(lvalue);
189 assert(rvalue);
190 assert(data);
191
192 r = qdisc_new_static(QDISC_KIND_FQ, network, filename, section_line, &qdisc);
193 if (r == -ENOMEM)
194 return log_oom();
195 if (r < 0)
196 return log_syntax(unit, LOG_ERR, filename, line, r,
197 "More than one kind of queueing discipline, ignoring assignment: %m");
198
199 fq = FQ(qdisc);
200
c03ef420 201 if (STR_IN_SET(lvalue, "QuantumBytes", "Quantum"))
e83562e5 202 p = &fq->quantum;
c03ef420 203 else if (STR_IN_SET(lvalue, "InitialQuantumBytes", "InitialQuantum"))
e83562e5
YW
204 p = &fq->initial_quantum;
205 else
206 assert_not_reached("Invalid lvalue");
207
208 if (isempty(rvalue)) {
209 *p = 0;
210
211 qdisc = NULL;
212 return 0;
213 }
214
215 r = parse_size(rvalue, 1024, &sz);
216 if (r < 0) {
217 log_syntax(unit, LOG_ERR, filename, line, r,
218 "Failed to parse '%s=', ignoring assignment: %s",
219 lvalue, rvalue);
220 return 0;
221 }
222 if (sz > UINT32_MAX) {
223 log_syntax(unit, LOG_ERR, filename, line, r,
224 "Specified '%s=' is too large, ignoring assignment: %s",
225 lvalue, rvalue);
226 return 0;
227 }
228
229 *p = sz;
230 qdisc = NULL;
231
232 return 0;
233}
234
949fb07e 235int config_parse_fair_queueing_bool(
e83562e5
YW
236 const char *unit,
237 const char *filename,
238 unsigned line,
239 const char *section,
240 unsigned section_line,
241 const char *lvalue,
242 int ltype,
243 const char *rvalue,
244 void *data,
245 void *userdata) {
246
247 _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
ca58d00c 248 FairQueueing *fq;
e83562e5
YW
249 Network *network = data;
250 int r;
251
252 assert(filename);
253 assert(lvalue);
254 assert(rvalue);
255 assert(data);
256
257 r = qdisc_new_static(QDISC_KIND_FQ, network, filename, section_line, &qdisc);
258 if (r == -ENOMEM)
259 return log_oom();
260 if (r < 0)
261 return log_syntax(unit, LOG_ERR, filename, line, r,
262 "More than one kind of queueing discipline, ignoring assignment: %m");
263
264 fq = FQ(qdisc);
265
266 if (isempty(rvalue)) {
267 fq->pacing = -1;
268
269 qdisc = NULL;
270 return 0;
271 }
272
273 r = parse_boolean(rvalue);
274 if (r < 0) {
275 log_syntax(unit, LOG_ERR, filename, line, r,
276 "Failed to parse '%s=', ignoring assignment: %s",
277 lvalue, rvalue);
278 return 0;
279 }
280
281 fq->pacing = r;
282 qdisc = NULL;
283
284 return 0;
285}
286
949fb07e 287int config_parse_fair_queueing_usec(
e83562e5
YW
288 const char *unit,
289 const char *filename,
290 unsigned line,
291 const char *section,
292 unsigned section_line,
293 const char *lvalue,
294 int ltype,
295 const char *rvalue,
296 void *data,
297 void *userdata) {
298
299 _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
ca58d00c 300 FairQueueing *fq;
e83562e5
YW
301 Network *network = data;
302 usec_t sec;
303 int r;
304
305 assert(filename);
306 assert(lvalue);
307 assert(rvalue);
308 assert(data);
309
310 r = qdisc_new_static(QDISC_KIND_FQ, network, filename, section_line, &qdisc);
311 if (r == -ENOMEM)
312 return log_oom();
313 if (r < 0)
314 return log_syntax(unit, LOG_ERR, filename, line, r,
315 "More than one kind of queueing discipline, ignoring assignment: %m");
316
317 fq = FQ(qdisc);
318
319 if (isempty(rvalue)) {
320 fq->ce_threshold_usec = USEC_INFINITY;
321
322 qdisc = NULL;
323 return 0;
324 }
325
326 r = parse_sec(rvalue, &sec);
327 if (r < 0) {
328 log_syntax(unit, LOG_ERR, filename, line, r,
329 "Failed to parse '%s=', ignoring assignment: %s",
330 lvalue, rvalue);
331 return 0;
332 }
333 if (sec > UINT32_MAX) {
334 log_syntax(unit, LOG_ERR, filename, line, 0,
335 "Specified '%s=' is too large, ignoring assignment: %s",
336 lvalue, rvalue);
337 return 0;
338 }
339
340 fq->ce_threshold_usec = sec;
341 qdisc = NULL;
342
343 return 0;
344}
345
949fb07e 346int config_parse_fair_queueing_max_rate(
e83562e5
YW
347 const char *unit,
348 const char *filename,
349 unsigned line,
350 const char *section,
351 unsigned section_line,
352 const char *lvalue,
353 int ltype,
354 const char *rvalue,
355 void *data,
356 void *userdata) {
357
358 _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
ca58d00c 359 FairQueueing *fq;
e83562e5
YW
360 Network *network = data;
361 uint64_t sz;
362 int r;
363
364 assert(filename);
365 assert(lvalue);
366 assert(rvalue);
367 assert(data);
368
369 r = qdisc_new_static(QDISC_KIND_FQ, network, filename, section_line, &qdisc);
370 if (r == -ENOMEM)
371 return log_oom();
372 if (r < 0)
373 return log_syntax(unit, LOG_ERR, filename, line, r,
374 "More than one kind of queueing discipline, ignoring assignment: %m");
375
376 fq = FQ(qdisc);
377
378 if (isempty(rvalue)) {
379 fq->max_rate = 0;
380
381 qdisc = NULL;
382 return 0;
383 }
384
385 r = parse_size(rvalue, 1000, &sz);
386 if (r < 0) {
387 log_syntax(unit, LOG_ERR, filename, line, r,
388 "Failed to parse '%s=', ignoring assignment: %s",
389 lvalue, rvalue);
390 return 0;
391 }
392 if (sz / 8 > UINT32_MAX) {
393 log_syntax(unit, LOG_ERR, filename, line, 0,
394 "Specified '%s=' is too large, ignoring assignment: %s",
395 lvalue, rvalue);
396 return 0;
397 }
398
399 fq->max_rate = sz / 8;
400 qdisc = NULL;
401
402 return 0;
403}
404
7234b915 405const QDiscVTable fq_vtable = {
949fb07e 406 .init = fair_queueing_init,
ca58d00c 407 .object_size = sizeof(FairQueueing),
7234b915 408 .tca_kind = "fq",
949fb07e 409 .fill_message = fair_queueing_fill_message,
7234b915 410};