]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/tc/fq-codel.c
journal: Serialize __MONOTONIC_TIMESTAMP metadata field as well
[thirdparty/systemd.git] / src / network / tc / fq-codel.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later
4e5ef149
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 "netlink-util.h"
9#include "parse-util.h"
10#include "qdisc.h"
11#include "string-util.h"
c03ef420 12#include "strv.h"
4e5ef149 13
18de0969
YW
14static int fair_queueing_controlled_delay_init(QDisc *qdisc) {
15 FairQueueingControlledDelay *fqcd;
ac810b75
YW
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
18de0969
YW
28static int fair_queueing_controlled_delay_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req) {
29 FairQueueingControlledDelay *fqcd;
4e5ef149
SS
30 int r;
31
32 assert(link);
e8c17dc0 33 assert(qdisc);
4e5ef149
SS
34 assert(req);
35
16924f54 36 assert_se(fqcd = FQ_CODEL(qdisc));
e8c17dc0 37
92c7593f 38 r = sd_netlink_message_open_container_union(req, TCA_OPTIONS, "fq_codel");
4e5ef149 39 if (r < 0)
16924f54 40 return r;
4e5ef149 41
ac810b75
YW
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)
16924f54 45 return r;
ac810b75
YW
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)
16924f54 51 return r;
ac810b75
YW
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)
16924f54 57 return r;
ac810b75
YW
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)
16924f54 63 return r;
ac810b75
YW
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)
16924f54 69 return r;
ac810b75
YW
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)
16924f54 75 return r;
ac810b75
YW
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)
16924f54 81 return r;
ac810b75
YW
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)
16924f54 87 return r;
ac810b75 88 }
4e5ef149
SS
89
90 r = sd_netlink_message_close_container(req);
91 if (r < 0)
16924f54 92 return r;
4e5ef149
SS
93
94 return 0;
95}
96
18de0969 97int config_parse_fair_queueing_controlled_delay_u32(
4e5ef149
SS
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;
18de0969 110 FairQueueingControlledDelay *fqcd;
99534007 111 Network *network = ASSERT_PTR(data);
ac810b75 112 uint32_t *p;
4e5ef149
SS
113 int r;
114
115 assert(filename);
116 assert(lvalue);
117 assert(rvalue);
4e5ef149 118
e8c17dc0
YW
119 r = qdisc_new_static(QDISC_KIND_FQ_CODEL, network, filename, section_line, &qdisc);
120 if (r == -ENOMEM)
121 return log_oom();
d96edb2c
YW
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 }
e8c17dc0
YW
127
128 fqcd = FQ_CODEL(qdisc);
4e5ef149 129
18de0969 130 if (streq(lvalue, "PacketLimit"))
ac810b75 131 p = &fqcd->packet_limit;
18de0969 132 else if (streq(lvalue, "Flows"))
ac810b75
YW
133 p = &fqcd->flows;
134 else
04499a70 135 assert_not_reached();
ac810b75 136
4e5ef149 137 if (isempty(rvalue)) {
ac810b75 138 *p = 0;
4e5ef149 139
0132453c 140 TAKE_PTR(qdisc);
4e5ef149
SS
141 return 0;
142 }
143
ac810b75 144 r = safe_atou32(rvalue, p);
4e5ef149 145 if (r < 0) {
d96edb2c 146 log_syntax(unit, LOG_WARNING, filename, line, r,
4e5ef149
SS
147 "Failed to parse '%s=', ignoring assignment: %s",
148 lvalue, rvalue);
149 return 0;
150 }
151
0132453c 152 TAKE_PTR(qdisc);
4e5ef149
SS
153
154 return 0;
155}
e8c17dc0 156
18de0969 157int config_parse_fair_queueing_controlled_delay_usec(
ac810b75
YW
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;
18de0969 170 FairQueueingControlledDelay *fqcd;
99534007 171 Network *network = ASSERT_PTR(data);
ac810b75
YW
172 usec_t *p;
173 int r;
174
175 assert(filename);
176 assert(lvalue);
177 assert(rvalue);
ac810b75
YW
178
179 r = qdisc_new_static(QDISC_KIND_FQ_CODEL, network, filename, section_line, &qdisc);
180 if (r == -ENOMEM)
181 return log_oom();
d96edb2c
YW
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 }
ac810b75
YW
187
188 fqcd = FQ_CODEL(qdisc);
189
18de0969 190 if (streq(lvalue, "TargetSec"))
ac810b75 191 p = &fqcd->target_usec;
18de0969 192 else if (streq(lvalue, "IntervalSec"))
ac810b75 193 p = &fqcd->interval_usec;
18de0969 194 else if (streq(lvalue, "CEThresholdSec"))
ac810b75
YW
195 p = &fqcd->ce_threshold_usec;
196 else
04499a70 197 assert_not_reached();
ac810b75
YW
198
199 if (isempty(rvalue)) {
18de0969 200 if (streq(lvalue, "CEThresholdSec"))
ac810b75
YW
201 *p = USEC_INFINITY;
202 else
203 *p = 0;
204
0132453c 205 TAKE_PTR(qdisc);
ac810b75
YW
206 return 0;
207 }
208
209 r = parse_sec(rvalue, p);
210 if (r < 0) {
d96edb2c 211 log_syntax(unit, LOG_WARNING, filename, line, r,
ac810b75
YW
212 "Failed to parse '%s=', ignoring assignment: %s",
213 lvalue, rvalue);
214 return 0;
215 }
216
0132453c 217 TAKE_PTR(qdisc);
ac810b75
YW
218
219 return 0;
220}
221
18de0969 222int config_parse_fair_queueing_controlled_delay_bool(
ac810b75
YW
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;
18de0969 235 FairQueueingControlledDelay *fqcd;
99534007 236 Network *network = ASSERT_PTR(data);
ac810b75
YW
237 int r;
238
239 assert(filename);
240 assert(lvalue);
241 assert(rvalue);
ac810b75
YW
242
243 r = qdisc_new_static(QDISC_KIND_FQ_CODEL, network, filename, section_line, &qdisc);
244 if (r == -ENOMEM)
245 return log_oom();
d96edb2c
YW
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 }
ac810b75
YW
251
252 fqcd = FQ_CODEL(qdisc);
253
b71a721f 254 r = parse_tristate(rvalue, &fqcd->ecn);
ac810b75 255 if (r < 0) {
d96edb2c 256 log_syntax(unit, LOG_WARNING, filename, line, r,
ac810b75
YW
257 "Failed to parse '%s=', ignoring assignment: %s",
258 lvalue, rvalue);
259 return 0;
260 }
261
0132453c 262 TAKE_PTR(qdisc);
ac810b75
YW
263
264 return 0;
265}
266
18de0969 267int config_parse_fair_queueing_controlled_delay_size(
ac810b75
YW
268 const char *unit,
269 const char *filename,
270 unsigned line,
271 const char *section,
272 unsigned section_line,
273 const char *lvalue,
274 int ltype,
275 const char *rvalue,
276 void *data,
277 void *userdata) {
278
279 _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
18de0969 280 FairQueueingControlledDelay *fqcd;
99534007 281 Network *network = ASSERT_PTR(data);
ac810b75
YW
282 uint64_t sz;
283 uint32_t *p;
284 int r;
285
286 assert(filename);
287 assert(lvalue);
288 assert(rvalue);
ac810b75
YW
289
290 r = qdisc_new_static(QDISC_KIND_FQ_CODEL, network, filename, section_line, &qdisc);
291 if (r == -ENOMEM)
292 return log_oom();
d96edb2c
YW
293 if (r < 0) {
294 log_syntax(unit, LOG_WARNING, filename, line, r,
295 "More than one kind of queueing discipline, ignoring assignment: %m");
296 return 0;
297 }
ac810b75
YW
298
299 fqcd = FQ_CODEL(qdisc);
300
c03ef420 301 if (STR_IN_SET(lvalue, "MemoryLimitBytes", "MemoryLimit"))
ac810b75 302 p = &fqcd->memory_limit;
c03ef420 303 else if (STR_IN_SET(lvalue, "QuantumBytes", "Quantum"))
ac810b75
YW
304 p = &fqcd->quantum;
305 else
04499a70 306 assert_not_reached();
ac810b75
YW
307
308 if (isempty(rvalue)) {
c03ef420 309 if (STR_IN_SET(lvalue, "MemoryLimitBytes", "MemoryLimit"))
ac810b75
YW
310 *p = UINT32_MAX;
311 else
312 *p = 0;
313
0132453c 314 TAKE_PTR(qdisc);
ac810b75
YW
315 return 0;
316 }
317
318 r = parse_size(rvalue, 1024, &sz);
319 if (r < 0) {
d96edb2c 320 log_syntax(unit, LOG_WARNING, filename, line, r,
ac810b75
YW
321 "Failed to parse '%s=', ignoring assignment: %s",
322 lvalue, rvalue);
323 return 0;
324 }
325 if (sz >= UINT32_MAX) {
d96edb2c 326 log_syntax(unit, LOG_WARNING, filename, line, 0,
ac810b75
YW
327 "Specified '%s=' is too large, ignoring assignment: %s",
328 lvalue, rvalue);
329 return 0;
330 }
331
332 *p = sz;
0132453c 333 TAKE_PTR(qdisc);
ac810b75
YW
334
335 return 0;
336}
337
e8c17dc0 338const QDiscVTable fq_codel_vtable = {
18de0969 339 .object_size = sizeof(FairQueueingControlledDelay),
e8c17dc0 340 .tca_kind = "fq_codel",
18de0969
YW
341 .init = fair_queueing_controlled_delay_init,
342 .fill_message = fair_queueing_controlled_delay_fill_message,
e8c17dc0 343};