]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/tc/fq-codel.c
tree-wide: use ASSERT_PTR more
[thirdparty/systemd.git] / src / network / tc / fq-codel.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later
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 "netlink-util.h"
9 #include "parse-util.h"
10 #include "qdisc.h"
11 #include "string-util.h"
12 #include "strv.h"
13
14 static int fair_queueing_controlled_delay_init(QDisc *qdisc) {
15 FairQueueingControlledDelay *fqcd;
16
17 assert(qdisc);
18
19 fqcd = FQ_CODEL(qdisc);
20
21 fqcd->memory_limit = UINT32_MAX;
22 fqcd->ce_threshold_usec = USEC_INFINITY;
23 fqcd->ecn = -1;
24
25 return 0;
26 }
27
28 static int fair_queueing_controlled_delay_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req) {
29 FairQueueingControlledDelay *fqcd;
30 int r;
31
32 assert(link);
33 assert(qdisc);
34 assert(req);
35
36 assert_se(fqcd = FQ_CODEL(qdisc));
37
38 r = sd_netlink_message_open_container_union(req, TCA_OPTIONS, "fq_codel");
39 if (r < 0)
40 return r;
41
42 if (fqcd->packet_limit > 0) {
43 r = sd_netlink_message_append_u32(req, TCA_FQ_CODEL_LIMIT, fqcd->packet_limit);
44 if (r < 0)
45 return r;
46 }
47
48 if (fqcd->flows > 0) {
49 r = sd_netlink_message_append_u32(req, TCA_FQ_CODEL_FLOWS, fqcd->flows);
50 if (r < 0)
51 return r;
52 }
53
54 if (fqcd->quantum > 0) {
55 r = sd_netlink_message_append_u32(req, TCA_FQ_CODEL_QUANTUM, fqcd->quantum);
56 if (r < 0)
57 return r;
58 }
59
60 if (fqcd->interval_usec > 0) {
61 r = sd_netlink_message_append_u32(req, TCA_FQ_CODEL_INTERVAL, fqcd->interval_usec);
62 if (r < 0)
63 return r;
64 }
65
66 if (fqcd->target_usec > 0) {
67 r = sd_netlink_message_append_u32(req, TCA_FQ_CODEL_TARGET, fqcd->target_usec);
68 if (r < 0)
69 return r;
70 }
71
72 if (fqcd->ecn >= 0) {
73 r = sd_netlink_message_append_u32(req, TCA_FQ_CODEL_ECN, fqcd->ecn);
74 if (r < 0)
75 return r;
76 }
77
78 if (fqcd->ce_threshold_usec != USEC_INFINITY) {
79 r = sd_netlink_message_append_u32(req, TCA_FQ_CODEL_CE_THRESHOLD, fqcd->ce_threshold_usec);
80 if (r < 0)
81 return r;
82 }
83
84 if (fqcd->memory_limit != UINT32_MAX) {
85 r = sd_netlink_message_append_u32(req, TCA_FQ_CODEL_MEMORY_LIMIT, fqcd->memory_limit);
86 if (r < 0)
87 return r;
88 }
89
90 r = sd_netlink_message_close_container(req);
91 if (r < 0)
92 return r;
93
94 return 0;
95 }
96
97 int config_parse_fair_queueing_controlled_delay_u32(
98 const char *unit,
99 const char *filename,
100 unsigned line,
101 const char *section,
102 unsigned section_line,
103 const char *lvalue,
104 int ltype,
105 const char *rvalue,
106 void *data,
107 void *userdata) {
108
109 _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
110 FairQueueingControlledDelay *fqcd;
111 Network *network = ASSERT_PTR(data);
112 uint32_t *p;
113 int r;
114
115 assert(filename);
116 assert(lvalue);
117 assert(rvalue);
118
119 r = qdisc_new_static(QDISC_KIND_FQ_CODEL, network, filename, section_line, &qdisc);
120 if (r == -ENOMEM)
121 return log_oom();
122 if (r < 0) {
123 log_syntax(unit, LOG_WARNING, filename, line, r,
124 "More than one kind of queueing discipline, ignoring assignment: %m");
125 return 0;
126 }
127
128 fqcd = FQ_CODEL(qdisc);
129
130 if (streq(lvalue, "PacketLimit"))
131 p = &fqcd->packet_limit;
132 else if (streq(lvalue, "Flows"))
133 p = &fqcd->flows;
134 else
135 assert_not_reached();
136
137 if (isempty(rvalue)) {
138 *p = 0;
139
140 TAKE_PTR(qdisc);
141 return 0;
142 }
143
144 r = safe_atou32(rvalue, p);
145 if (r < 0) {
146 log_syntax(unit, LOG_WARNING, filename, line, r,
147 "Failed to parse '%s=', ignoring assignment: %s",
148 lvalue, rvalue);
149 return 0;
150 }
151
152 TAKE_PTR(qdisc);
153
154 return 0;
155 }
156
157 int config_parse_fair_queueing_controlled_delay_usec(
158 const char *unit,
159 const char *filename,
160 unsigned line,
161 const char *section,
162 unsigned section_line,
163 const char *lvalue,
164 int ltype,
165 const char *rvalue,
166 void *data,
167 void *userdata) {
168
169 _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
170 FairQueueingControlledDelay *fqcd;
171 Network *network = ASSERT_PTR(data);
172 usec_t *p;
173 int r;
174
175 assert(filename);
176 assert(lvalue);
177 assert(rvalue);
178
179 r = qdisc_new_static(QDISC_KIND_FQ_CODEL, network, filename, section_line, &qdisc);
180 if (r == -ENOMEM)
181 return log_oom();
182 if (r < 0) {
183 log_syntax(unit, LOG_WARNING, filename, line, r,
184 "More than one kind of queueing discipline, ignoring assignment: %m");
185 return 0;
186 }
187
188 fqcd = FQ_CODEL(qdisc);
189
190 if (streq(lvalue, "TargetSec"))
191 p = &fqcd->target_usec;
192 else if (streq(lvalue, "IntervalSec"))
193 p = &fqcd->interval_usec;
194 else if (streq(lvalue, "CEThresholdSec"))
195 p = &fqcd->ce_threshold_usec;
196 else
197 assert_not_reached();
198
199 if (isempty(rvalue)) {
200 if (streq(lvalue, "CEThresholdSec"))
201 *p = USEC_INFINITY;
202 else
203 *p = 0;
204
205 TAKE_PTR(qdisc);
206 return 0;
207 }
208
209 r = parse_sec(rvalue, p);
210 if (r < 0) {
211 log_syntax(unit, LOG_WARNING, filename, line, r,
212 "Failed to parse '%s=', ignoring assignment: %s",
213 lvalue, rvalue);
214 return 0;
215 }
216
217 TAKE_PTR(qdisc);
218
219 return 0;
220 }
221
222 int config_parse_fair_queueing_controlled_delay_bool(
223 const char *unit,
224 const char *filename,
225 unsigned line,
226 const char *section,
227 unsigned section_line,
228 const char *lvalue,
229 int ltype,
230 const char *rvalue,
231 void *data,
232 void *userdata) {
233
234 _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
235 FairQueueingControlledDelay *fqcd;
236 Network *network = ASSERT_PTR(data);
237 int r;
238
239 assert(filename);
240 assert(lvalue);
241 assert(rvalue);
242
243 r = qdisc_new_static(QDISC_KIND_FQ_CODEL, network, filename, section_line, &qdisc);
244 if (r == -ENOMEM)
245 return log_oom();
246 if (r < 0) {
247 log_syntax(unit, LOG_WARNING, filename, line, r,
248 "More than one kind of queueing discipline, ignoring assignment: %m");
249 return 0;
250 }
251
252 fqcd = FQ_CODEL(qdisc);
253
254 if (isempty(rvalue)) {
255 fqcd->ecn = -1;
256
257 TAKE_PTR(qdisc);
258 return 0;
259 }
260
261 r = parse_boolean(rvalue);
262 if (r < 0) {
263 log_syntax(unit, LOG_WARNING, filename, line, r,
264 "Failed to parse '%s=', ignoring assignment: %s",
265 lvalue, rvalue);
266 return 0;
267 }
268
269 fqcd->ecn = r;
270 TAKE_PTR(qdisc);
271
272 return 0;
273 }
274
275 int config_parse_fair_queueing_controlled_delay_size(
276 const char *unit,
277 const char *filename,
278 unsigned line,
279 const char *section,
280 unsigned section_line,
281 const char *lvalue,
282 int ltype,
283 const char *rvalue,
284 void *data,
285 void *userdata) {
286
287 _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
288 FairQueueingControlledDelay *fqcd;
289 Network *network = ASSERT_PTR(data);
290 uint64_t sz;
291 uint32_t *p;
292 int r;
293
294 assert(filename);
295 assert(lvalue);
296 assert(rvalue);
297
298 r = qdisc_new_static(QDISC_KIND_FQ_CODEL, network, filename, section_line, &qdisc);
299 if (r == -ENOMEM)
300 return log_oom();
301 if (r < 0) {
302 log_syntax(unit, LOG_WARNING, filename, line, r,
303 "More than one kind of queueing discipline, ignoring assignment: %m");
304 return 0;
305 }
306
307 fqcd = FQ_CODEL(qdisc);
308
309 if (STR_IN_SET(lvalue, "MemoryLimitBytes", "MemoryLimit"))
310 p = &fqcd->memory_limit;
311 else if (STR_IN_SET(lvalue, "QuantumBytes", "Quantum"))
312 p = &fqcd->quantum;
313 else
314 assert_not_reached();
315
316 if (isempty(rvalue)) {
317 if (STR_IN_SET(lvalue, "MemoryLimitBytes", "MemoryLimit"))
318 *p = UINT32_MAX;
319 else
320 *p = 0;
321
322 TAKE_PTR(qdisc);
323 return 0;
324 }
325
326 r = parse_size(rvalue, 1024, &sz);
327 if (r < 0) {
328 log_syntax(unit, LOG_WARNING, filename, line, r,
329 "Failed to parse '%s=', ignoring assignment: %s",
330 lvalue, rvalue);
331 return 0;
332 }
333 if (sz >= UINT32_MAX) {
334 log_syntax(unit, LOG_WARNING, filename, line, 0,
335 "Specified '%s=' is too large, ignoring assignment: %s",
336 lvalue, rvalue);
337 return 0;
338 }
339
340 *p = sz;
341 TAKE_PTR(qdisc);
342
343 return 0;
344 }
345
346 const QDiscVTable fq_codel_vtable = {
347 .object_size = sizeof(FairQueueingControlledDelay),
348 .tca_kind = "fq_codel",
349 .init = fair_queueing_controlled_delay_init,
350 .fill_message = fair_queueing_controlled_delay_fill_message,
351 };