]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later |
ad8352f4 SS |
2 | * Copyright © 2020 VMware, Inc. */ |
3 | ||
4 | #include <linux/pkt_sched.h> | |
5 | ||
6 | #include "alloc-util.h" | |
7 | #include "cake.h" | |
8 | #include "conf-parser.h" | |
9 | #include "netlink-util.h" | |
10 | #include "parse-util.h" | |
11 | #include "qdisc.h" | |
b6eccfda | 12 | #include "string-table.h" |
ad8352f4 SS |
13 | #include "string-util.h" |
14 | ||
025cd94e YW |
15 | static int cake_init(QDisc *qdisc) { |
16 | CommonApplicationsKeptEnhanced *c; | |
17 | ||
18 | assert(qdisc); | |
19 | ||
20 | c = CAKE(qdisc); | |
21 | ||
22 | c->autorate = -1; | |
b6eccfda | 23 | c->compensation_mode = _CAKE_COMPENSATION_MODE_INVALID; |
1c7a81e6 | 24 | c->raw = -1; |
a049cf16 | 25 | c->flow_isolation_mode = _CAKE_FLOW_ISOLATION_MODE_INVALID; |
4bff8086 | 26 | c->nat = -1; |
fe8e156e | 27 | c->preset = _CAKE_PRESET_INVALID; |
d05dce95 | 28 | c->wash = -1; |
35896db4 | 29 | c->split_gso = -1; |
025cd94e YW |
30 | |
31 | return 0; | |
32 | } | |
33 | ||
ad8352f4 SS |
34 | static int cake_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req) { |
35 | CommonApplicationsKeptEnhanced *c; | |
36 | int r; | |
37 | ||
38 | assert(link); | |
39 | assert(qdisc); | |
40 | assert(req); | |
41 | ||
16924f54 | 42 | assert_se(c = CAKE(qdisc)); |
ad8352f4 SS |
43 | |
44 | r = sd_netlink_message_open_container_union(req, TCA_OPTIONS, "cake"); | |
45 | if (r < 0) | |
16924f54 | 46 | return r; |
ad8352f4 SS |
47 | |
48 | if (c->bandwidth > 0) { | |
49 | r = sd_netlink_message_append_u64(req, TCA_CAKE_BASE_RATE64, c->bandwidth); | |
50 | if (r < 0) | |
16924f54 | 51 | return r; |
ad8352f4 SS |
52 | } |
53 | ||
025cd94e YW |
54 | if (c->autorate >= 0) { |
55 | r = sd_netlink_message_append_u32(req, TCA_CAKE_AUTORATE, c->autorate); | |
56 | if (r < 0) | |
16924f54 | 57 | return r; |
025cd94e YW |
58 | } |
59 | ||
3a86a31e YW |
60 | if (c->overhead_set) { |
61 | r = sd_netlink_message_append_s32(req, TCA_CAKE_OVERHEAD, c->overhead); | |
62 | if (r < 0) | |
16924f54 | 63 | return r; |
3a86a31e | 64 | } |
ad8352f4 | 65 | |
863542e1 YW |
66 | if (c->mpu > 0) { |
67 | r = sd_netlink_message_append_u32(req, TCA_CAKE_MPU, c->mpu); | |
68 | if (r < 0) | |
16924f54 | 69 | return r; |
863542e1 YW |
70 | } |
71 | ||
b6eccfda YW |
72 | if (c->compensation_mode >= 0) { |
73 | r = sd_netlink_message_append_u32(req, TCA_CAKE_ATM, c->compensation_mode); | |
74 | if (r < 0) | |
16924f54 | 75 | return r; |
b6eccfda YW |
76 | } |
77 | ||
1c7a81e6 YW |
78 | if (c->raw > 0) { |
79 | /* TCA_CAKE_RAW attribute is mostly a flag, not boolean. */ | |
80 | r = sd_netlink_message_append_u32(req, TCA_CAKE_RAW, 0); | |
81 | if (r < 0) | |
16924f54 | 82 | return r; |
1c7a81e6 YW |
83 | } |
84 | ||
a049cf16 YW |
85 | if (c->flow_isolation_mode >= 0) { |
86 | r = sd_netlink_message_append_u32(req, TCA_CAKE_FLOW_MODE, c->flow_isolation_mode); | |
87 | if (r < 0) | |
16924f54 | 88 | return r; |
a049cf16 YW |
89 | } |
90 | ||
4bff8086 YW |
91 | if (c->nat >= 0) { |
92 | r = sd_netlink_message_append_u32(req, TCA_CAKE_NAT, c->nat); | |
93 | if (r < 0) | |
16924f54 | 94 | return r; |
4bff8086 YW |
95 | } |
96 | ||
fe8e156e YW |
97 | if (c->preset >= 0) { |
98 | r = sd_netlink_message_append_u32(req, TCA_CAKE_DIFFSERV_MODE, c->preset); | |
99 | if (r < 0) | |
16924f54 | 100 | return r; |
fe8e156e YW |
101 | } |
102 | ||
049b66cc YW |
103 | if (c->fwmark > 0) { |
104 | r = sd_netlink_message_append_u32(req, TCA_CAKE_FWMARK, c->fwmark); | |
105 | if (r < 0) | |
16924f54 | 106 | return r; |
049b66cc YW |
107 | } |
108 | ||
d05dce95 YW |
109 | if (c->wash >= 0) { |
110 | r = sd_netlink_message_append_u32(req, TCA_CAKE_WASH, c->wash); | |
111 | if (r < 0) | |
16924f54 | 112 | return r; |
d05dce95 YW |
113 | } |
114 | ||
35896db4 | 115 | if (c->split_gso >= 0) { |
4883a5ec | 116 | r = sd_netlink_message_append_u32(req, TCA_CAKE_SPLIT_GSO, c->split_gso); |
35896db4 | 117 | if (r < 0) |
16924f54 | 118 | return r; |
35896db4 YW |
119 | } |
120 | ||
ad8352f4 SS |
121 | r = sd_netlink_message_close_container(req); |
122 | if (r < 0) | |
16924f54 | 123 | return r; |
ad8352f4 SS |
124 | |
125 | return 0; | |
126 | } | |
127 | ||
128 | int config_parse_cake_bandwidth( | |
129 | const char *unit, | |
130 | const char *filename, | |
131 | unsigned line, | |
132 | const char *section, | |
133 | unsigned section_line, | |
134 | const char *lvalue, | |
135 | int ltype, | |
136 | const char *rvalue, | |
137 | void *data, | |
138 | void *userdata) { | |
139 | ||
140 | _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL; | |
141 | CommonApplicationsKeptEnhanced *c; | |
99534007 | 142 | Network *network = ASSERT_PTR(data); |
ad8352f4 SS |
143 | uint64_t k; |
144 | int r; | |
145 | ||
146 | assert(filename); | |
147 | assert(lvalue); | |
148 | assert(rvalue); | |
ad8352f4 SS |
149 | |
150 | r = qdisc_new_static(QDISC_KIND_CAKE, network, filename, section_line, &qdisc); | |
151 | if (r == -ENOMEM) | |
152 | return log_oom(); | |
d96edb2c YW |
153 | if (r < 0) { |
154 | log_syntax(unit, LOG_WARNING, filename, line, r, | |
155 | "More than one kind of queueing discipline, ignoring assignment: %m"); | |
156 | return 0; | |
157 | } | |
ad8352f4 SS |
158 | |
159 | c = CAKE(qdisc); | |
160 | ||
161 | if (isempty(rvalue)) { | |
162 | c->bandwidth = 0; | |
163 | ||
0132453c | 164 | TAKE_PTR(qdisc); |
ad8352f4 SS |
165 | return 0; |
166 | } | |
167 | ||
168 | r = parse_size(rvalue, 1000, &k); | |
169 | if (r < 0) { | |
d96edb2c | 170 | log_syntax(unit, LOG_WARNING, filename, line, r, |
ad8352f4 SS |
171 | "Failed to parse '%s=', ignoring assignment: %s", |
172 | lvalue, rvalue); | |
173 | return 0; | |
174 | } | |
175 | ||
176 | c->bandwidth = k/8; | |
0132453c | 177 | TAKE_PTR(qdisc); |
ad8352f4 SS |
178 | |
179 | return 0; | |
180 | } | |
181 | ||
182 | int config_parse_cake_overhead( | |
183 | const char *unit, | |
184 | const char *filename, | |
185 | unsigned line, | |
186 | const char *section, | |
187 | unsigned section_line, | |
188 | const char *lvalue, | |
189 | int ltype, | |
190 | const char *rvalue, | |
191 | void *data, | |
192 | void *userdata) { | |
193 | ||
194 | _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL; | |
195 | CommonApplicationsKeptEnhanced *c; | |
99534007 | 196 | Network *network = ASSERT_PTR(data); |
ad8352f4 SS |
197 | int32_t v; |
198 | int r; | |
199 | ||
200 | assert(filename); | |
201 | assert(lvalue); | |
202 | assert(rvalue); | |
ad8352f4 SS |
203 | |
204 | r = qdisc_new_static(QDISC_KIND_CAKE, network, filename, section_line, &qdisc); | |
205 | if (r == -ENOMEM) | |
206 | return log_oom(); | |
d96edb2c YW |
207 | if (r < 0) { |
208 | log_syntax(unit, LOG_WARNING, filename, line, r, | |
209 | "More than one kind of queueing discipline, ignoring assignment: %m"); | |
210 | return 0; | |
211 | } | |
ad8352f4 SS |
212 | |
213 | c = CAKE(qdisc); | |
214 | ||
215 | if (isempty(rvalue)) { | |
3a86a31e | 216 | c->overhead_set = false; |
0132453c | 217 | TAKE_PTR(qdisc); |
ad8352f4 SS |
218 | return 0; |
219 | } | |
220 | ||
221 | r = safe_atoi32(rvalue, &v); | |
222 | if (r < 0) { | |
d96edb2c | 223 | log_syntax(unit, LOG_WARNING, filename, line, r, |
c03ef420 YW |
224 | "Failed to parse '%s=', ignoring assignment: %s", |
225 | lvalue, rvalue); | |
ad8352f4 SS |
226 | return 0; |
227 | } | |
228 | if (v < -64 || v > 256) { | |
d96edb2c | 229 | log_syntax(unit, LOG_WARNING, filename, line, 0, |
c03ef420 YW |
230 | "Invalid '%s=', ignoring assignment: %s", |
231 | lvalue, rvalue); | |
ad8352f4 SS |
232 | return 0; |
233 | } | |
234 | ||
235 | c->overhead = v; | |
3a86a31e | 236 | c->overhead_set = true; |
0132453c | 237 | TAKE_PTR(qdisc); |
ad8352f4 SS |
238 | return 0; |
239 | } | |
240 | ||
863542e1 YW |
241 | int config_parse_cake_mpu( |
242 | const char *unit, | |
243 | const char *filename, | |
244 | unsigned line, | |
245 | const char *section, | |
246 | unsigned section_line, | |
247 | const char *lvalue, | |
248 | int ltype, | |
249 | const char *rvalue, | |
250 | void *data, | |
251 | void *userdata) { | |
252 | ||
253 | _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL; | |
254 | CommonApplicationsKeptEnhanced *c; | |
99534007 | 255 | Network *network = ASSERT_PTR(data); |
863542e1 YW |
256 | uint32_t v; |
257 | int r; | |
258 | ||
259 | assert(filename); | |
260 | assert(lvalue); | |
261 | assert(rvalue); | |
863542e1 YW |
262 | |
263 | r = qdisc_new_static(QDISC_KIND_CAKE, network, filename, section_line, &qdisc); | |
264 | if (r == -ENOMEM) | |
265 | return log_oom(); | |
266 | if (r < 0) { | |
267 | log_syntax(unit, LOG_WARNING, filename, line, r, | |
268 | "More than one kind of queueing discipline, ignoring assignment: %m"); | |
269 | return 0; | |
270 | } | |
271 | ||
272 | c = CAKE(qdisc); | |
273 | ||
274 | if (isempty(rvalue)) { | |
275 | c->mpu = 0; | |
276 | TAKE_PTR(qdisc); | |
277 | return 0; | |
278 | } | |
279 | ||
280 | r = safe_atou32(rvalue, &v); | |
281 | if (r < 0) { | |
282 | log_syntax(unit, LOG_WARNING, filename, line, r, | |
283 | "Failed to parse '%s=', ignoring assignment: %s", | |
284 | lvalue, rvalue); | |
285 | return 0; | |
286 | } | |
287 | if (v <= 0 || v > 256) { | |
288 | log_syntax(unit, LOG_WARNING, filename, line, 0, | |
289 | "Invalid '%s=', ignoring assignment: %s", | |
290 | lvalue, rvalue); | |
291 | return 0; | |
292 | } | |
293 | ||
294 | c->mpu = v; | |
295 | TAKE_PTR(qdisc); | |
296 | return 0; | |
297 | } | |
298 | ||
025cd94e YW |
299 | int config_parse_cake_tristate( |
300 | const char *unit, | |
301 | const char *filename, | |
302 | unsigned line, | |
303 | const char *section, | |
304 | unsigned section_line, | |
305 | const char *lvalue, | |
306 | int ltype, | |
307 | const char *rvalue, | |
308 | void *data, | |
309 | void *userdata) { | |
310 | ||
311 | _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL; | |
312 | CommonApplicationsKeptEnhanced *c; | |
99534007 | 313 | Network *network = ASSERT_PTR(data); |
025cd94e YW |
314 | int *dest, r; |
315 | ||
316 | assert(filename); | |
317 | assert(lvalue); | |
318 | assert(rvalue); | |
025cd94e YW |
319 | |
320 | r = qdisc_new_static(QDISC_KIND_CAKE, network, filename, section_line, &qdisc); | |
321 | if (r == -ENOMEM) | |
322 | return log_oom(); | |
323 | if (r < 0) { | |
324 | log_syntax(unit, LOG_WARNING, filename, line, r, | |
325 | "More than one kind of queueing discipline, ignoring assignment: %m"); | |
326 | return 0; | |
327 | } | |
328 | ||
329 | c = CAKE(qdisc); | |
330 | ||
331 | if (streq(lvalue, "AutoRateIngress")) | |
332 | dest = &c->autorate; | |
1c7a81e6 YW |
333 | else if (streq(lvalue, "UseRawPacketSize")) |
334 | dest = &c->raw; | |
4bff8086 YW |
335 | else if (streq(lvalue, "NAT")) |
336 | dest = &c->nat; | |
d05dce95 YW |
337 | else if (streq(lvalue, "Wash")) |
338 | dest = &c->wash; | |
35896db4 YW |
339 | else if (streq(lvalue, "SplitGSO")) |
340 | dest = &c->split_gso; | |
025cd94e YW |
341 | else |
342 | assert_not_reached(); | |
343 | ||
344 | if (isempty(rvalue)) { | |
345 | *dest = -1; | |
346 | TAKE_PTR(qdisc); | |
347 | return 0; | |
348 | } | |
349 | ||
350 | r = parse_boolean(rvalue); | |
351 | if (r < 0) { | |
352 | log_syntax(unit, LOG_WARNING, filename, line, r, | |
353 | "Failed to parse '%s=', ignoring assignment: %s", | |
354 | lvalue, rvalue); | |
355 | return 0; | |
356 | } | |
357 | ||
358 | *dest = r; | |
359 | TAKE_PTR(qdisc); | |
360 | return 0; | |
361 | } | |
362 | ||
b6eccfda YW |
363 | static const char * const cake_compensation_mode_table[_CAKE_COMPENSATION_MODE_MAX] = { |
364 | [CAKE_COMPENSATION_MODE_NONE] = "none", | |
365 | [CAKE_COMPENSATION_MODE_ATM] = "atm", | |
366 | [CAKE_COMPENSATION_MODE_PTM] = "ptm", | |
367 | }; | |
368 | ||
369 | DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(cake_compensation_mode, CakeCompensationMode); | |
370 | ||
371 | int config_parse_cake_compensation_mode( | |
372 | const char *unit, | |
373 | const char *filename, | |
374 | unsigned line, | |
375 | const char *section, | |
376 | unsigned section_line, | |
377 | const char *lvalue, | |
378 | int ltype, | |
379 | const char *rvalue, | |
380 | void *data, | |
381 | void *userdata) { | |
382 | ||
383 | _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL; | |
384 | CommonApplicationsKeptEnhanced *c; | |
99534007 | 385 | Network *network = ASSERT_PTR(data); |
b6eccfda YW |
386 | CakeCompensationMode mode; |
387 | int r; | |
388 | ||
389 | assert(filename); | |
390 | assert(lvalue); | |
391 | assert(rvalue); | |
b6eccfda YW |
392 | |
393 | r = qdisc_new_static(QDISC_KIND_CAKE, network, filename, section_line, &qdisc); | |
394 | if (r == -ENOMEM) | |
395 | return log_oom(); | |
396 | if (r < 0) { | |
397 | log_syntax(unit, LOG_WARNING, filename, line, r, | |
398 | "More than one kind of queueing discipline, ignoring assignment: %m"); | |
399 | return 0; | |
400 | } | |
401 | ||
402 | c = CAKE(qdisc); | |
403 | ||
404 | if (isempty(rvalue)) { | |
405 | c->compensation_mode = _CAKE_COMPENSATION_MODE_INVALID; | |
406 | TAKE_PTR(qdisc); | |
407 | return 0; | |
408 | } | |
409 | ||
410 | mode = cake_compensation_mode_from_string(rvalue); | |
411 | if (mode < 0) { | |
412 | log_syntax(unit, LOG_WARNING, filename, line, mode, | |
413 | "Failed to parse '%s=', ignoring assignment: %s", | |
414 | lvalue, rvalue); | |
415 | return 0; | |
416 | } | |
417 | ||
418 | c->compensation_mode = mode; | |
419 | TAKE_PTR(qdisc); | |
420 | return 0; | |
421 | } | |
422 | ||
a049cf16 YW |
423 | static const char * const cake_flow_isolation_mode_table[_CAKE_FLOW_ISOLATION_MODE_MAX] = { |
424 | [CAKE_FLOW_ISOLATION_MODE_NONE] = "none", | |
425 | [CAKE_FLOW_ISOLATION_MODE_SRC_IP] = "src-host", | |
426 | [CAKE_FLOW_ISOLATION_MODE_DST_IP] = "dst-host", | |
427 | [CAKE_FLOW_ISOLATION_MODE_HOSTS] = "hosts", | |
428 | [CAKE_FLOW_ISOLATION_MODE_FLOWS] = "flows", | |
429 | [CAKE_FLOW_ISOLATION_MODE_DUAL_SRC] = "dual-src-host", | |
430 | [CAKE_FLOW_ISOLATION_MODE_DUAL_DST] = "dual-dst-host", | |
431 | [CAKE_FLOW_ISOLATION_MODE_TRIPLE] = "triple", | |
432 | }; | |
433 | ||
434 | DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(cake_flow_isolation_mode, CakeFlowIsolationMode); | |
435 | ||
436 | int config_parse_cake_flow_isolation_mode( | |
437 | const char *unit, | |
438 | const char *filename, | |
439 | unsigned line, | |
440 | const char *section, | |
441 | unsigned section_line, | |
442 | const char *lvalue, | |
443 | int ltype, | |
444 | const char *rvalue, | |
445 | void *data, | |
446 | void *userdata) { | |
447 | ||
448 | _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL; | |
449 | CommonApplicationsKeptEnhanced *c; | |
99534007 | 450 | Network *network = ASSERT_PTR(data); |
a049cf16 YW |
451 | CakeFlowIsolationMode mode; |
452 | int r; | |
453 | ||
454 | assert(filename); | |
455 | assert(lvalue); | |
456 | assert(rvalue); | |
a049cf16 YW |
457 | |
458 | r = qdisc_new_static(QDISC_KIND_CAKE, network, filename, section_line, &qdisc); | |
459 | if (r == -ENOMEM) | |
460 | return log_oom(); | |
461 | if (r < 0) { | |
462 | log_syntax(unit, LOG_WARNING, filename, line, r, | |
463 | "More than one kind of queueing discipline, ignoring assignment: %m"); | |
464 | return 0; | |
465 | } | |
466 | ||
467 | c = CAKE(qdisc); | |
468 | ||
469 | if (isempty(rvalue)) { | |
470 | c->flow_isolation_mode = _CAKE_FLOW_ISOLATION_MODE_INVALID; | |
471 | TAKE_PTR(qdisc); | |
472 | return 0; | |
473 | } | |
474 | ||
475 | mode = cake_flow_isolation_mode_from_string(rvalue); | |
476 | if (mode < 0) { | |
477 | log_syntax(unit, LOG_WARNING, filename, line, mode, | |
478 | "Failed to parse '%s=', ignoring assignment: %s", | |
479 | lvalue, rvalue); | |
480 | return 0; | |
481 | } | |
482 | ||
483 | c->flow_isolation_mode = mode; | |
484 | TAKE_PTR(qdisc); | |
485 | return 0; | |
486 | } | |
487 | ||
fe8e156e YW |
488 | static const char * const cake_priority_queueing_preset_table[_CAKE_PRESET_MAX] = { |
489 | [CAKE_PRESET_DIFFSERV3] = "diffserv3", | |
490 | [CAKE_PRESET_DIFFSERV4] = "diffserv4", | |
491 | [CAKE_PRESET_DIFFSERV8] = "diffserv8", | |
492 | [CAKE_PRESET_BESTEFFORT] = "besteffort", | |
493 | [CAKE_PRESET_PRECEDENCE] = "precedence", | |
494 | }; | |
495 | ||
496 | DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(cake_priority_queueing_preset, CakePriorityQueueingPreset); | |
497 | ||
498 | int config_parse_cake_priority_queueing_preset( | |
499 | const char *unit, | |
500 | const char *filename, | |
501 | unsigned line, | |
502 | const char *section, | |
503 | unsigned section_line, | |
504 | const char *lvalue, | |
505 | int ltype, | |
506 | const char *rvalue, | |
507 | void *data, | |
508 | void *userdata) { | |
509 | ||
510 | _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL; | |
511 | CommonApplicationsKeptEnhanced *c; | |
512 | CakePriorityQueueingPreset preset; | |
99534007 | 513 | Network *network = ASSERT_PTR(data); |
fe8e156e YW |
514 | int r; |
515 | ||
516 | assert(filename); | |
517 | assert(lvalue); | |
518 | assert(rvalue); | |
fe8e156e YW |
519 | |
520 | r = qdisc_new_static(QDISC_KIND_CAKE, network, filename, section_line, &qdisc); | |
521 | if (r == -ENOMEM) | |
522 | return log_oom(); | |
523 | if (r < 0) { | |
524 | log_syntax(unit, LOG_WARNING, filename, line, r, | |
525 | "More than one kind of queueing discipline, ignoring assignment: %m"); | |
526 | return 0; | |
527 | } | |
528 | ||
529 | c = CAKE(qdisc); | |
530 | ||
531 | if (isempty(rvalue)) { | |
532 | c->preset = _CAKE_PRESET_INVALID; | |
533 | TAKE_PTR(qdisc); | |
534 | return 0; | |
535 | } | |
536 | ||
537 | preset = cake_priority_queueing_preset_from_string(rvalue); | |
538 | if (preset < 0) { | |
539 | log_syntax(unit, LOG_WARNING, filename, line, preset, | |
540 | "Failed to parse '%s=', ignoring assignment: %s", | |
541 | lvalue, rvalue); | |
542 | return 0; | |
543 | } | |
544 | ||
545 | c->preset = preset; | |
546 | TAKE_PTR(qdisc); | |
547 | return 0; | |
548 | } | |
549 | ||
049b66cc YW |
550 | int config_parse_cake_fwmark( |
551 | const char *unit, | |
552 | const char *filename, | |
553 | unsigned line, | |
554 | const char *section, | |
555 | unsigned section_line, | |
556 | const char *lvalue, | |
557 | int ltype, | |
558 | const char *rvalue, | |
559 | void *data, | |
560 | void *userdata) { | |
561 | ||
562 | _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL; | |
563 | CommonApplicationsKeptEnhanced *c; | |
99534007 | 564 | Network *network = ASSERT_PTR(data); |
049b66cc YW |
565 | uint32_t fwmark; |
566 | int r; | |
567 | ||
568 | assert(filename); | |
569 | assert(lvalue); | |
570 | assert(rvalue); | |
049b66cc YW |
571 | |
572 | r = qdisc_new_static(QDISC_KIND_CAKE, network, filename, section_line, &qdisc); | |
573 | if (r == -ENOMEM) | |
574 | return log_oom(); | |
575 | if (r < 0) { | |
576 | log_syntax(unit, LOG_WARNING, filename, line, r, | |
577 | "More than one kind of queueing discipline, ignoring assignment: %m"); | |
578 | return 0; | |
579 | } | |
580 | ||
581 | c = CAKE(qdisc); | |
582 | ||
583 | if (isempty(rvalue)) { | |
584 | c->fwmark = 0; | |
585 | TAKE_PTR(qdisc); | |
586 | return 0; | |
587 | } | |
588 | ||
589 | r = safe_atou32(rvalue, &fwmark); | |
590 | if (r < 0) { | |
591 | log_syntax(unit, LOG_WARNING, filename, line, r, | |
592 | "Failed to parse '%s=', ignoring assignment: %s", | |
593 | lvalue, rvalue); | |
594 | return 0; | |
595 | } | |
596 | if (fwmark <= 0) { | |
597 | log_syntax(unit, LOG_WARNING, filename, line, 0, | |
598 | "Invalid '%s=', ignoring assignment: %s", | |
599 | lvalue, rvalue); | |
600 | return 0; | |
601 | } | |
602 | ||
603 | c->fwmark = fwmark; | |
604 | TAKE_PTR(qdisc); | |
605 | return 0; | |
606 | } | |
607 | ||
ad8352f4 SS |
608 | const QDiscVTable cake_vtable = { |
609 | .object_size = sizeof(CommonApplicationsKeptEnhanced), | |
610 | .tca_kind = "cake", | |
025cd94e | 611 | .init = cake_init, |
ad8352f4 SS |
612 | .fill_message = cake_fill_message, |
613 | }; |