1 /* SPDX-License-Identifier: LGPL-2.1-or-later
2 * Copyright © 2020 VMware, Inc. */
4 #include <linux/pkt_sched.h>
6 #include "alloc-util.h"
8 #include "conf-parser.h"
9 #include "netlink-util.h"
10 #include "parse-util.h"
12 #include "string-table.h"
13 #include "string-util.h"
15 static int cake_init(QDisc
*qdisc
) {
16 CommonApplicationsKeptEnhanced
*c
;
23 c
->compensation_mode
= _CAKE_COMPENSATION_MODE_INVALID
;
25 c
->flow_isolation_mode
= _CAKE_FLOW_ISOLATION_MODE_INVALID
;
27 c
->preset
= _CAKE_PRESET_INVALID
;
34 static int cake_fill_message(Link
*link
, QDisc
*qdisc
, sd_netlink_message
*req
) {
35 CommonApplicationsKeptEnhanced
*c
;
42 assert_se(c
= CAKE(qdisc
));
44 r
= sd_netlink_message_open_container_union(req
, TCA_OPTIONS
, "cake");
48 if (c
->bandwidth
> 0) {
49 r
= sd_netlink_message_append_u64(req
, TCA_CAKE_BASE_RATE64
, c
->bandwidth
);
54 if (c
->autorate
>= 0) {
55 r
= sd_netlink_message_append_u32(req
, TCA_CAKE_AUTORATE
, c
->autorate
);
60 if (c
->overhead_set
) {
61 r
= sd_netlink_message_append_s32(req
, TCA_CAKE_OVERHEAD
, c
->overhead
);
67 r
= sd_netlink_message_append_u32(req
, TCA_CAKE_MPU
, c
->mpu
);
72 if (c
->compensation_mode
>= 0) {
73 r
= sd_netlink_message_append_u32(req
, TCA_CAKE_ATM
, c
->compensation_mode
);
79 /* TCA_CAKE_RAW attribute is mostly a flag, not boolean. */
80 r
= sd_netlink_message_append_u32(req
, TCA_CAKE_RAW
, 0);
85 if (c
->flow_isolation_mode
>= 0) {
86 r
= sd_netlink_message_append_u32(req
, TCA_CAKE_FLOW_MODE
, c
->flow_isolation_mode
);
92 r
= sd_netlink_message_append_u32(req
, TCA_CAKE_NAT
, c
->nat
);
98 r
= sd_netlink_message_append_u32(req
, TCA_CAKE_DIFFSERV_MODE
, c
->preset
);
104 r
= sd_netlink_message_append_u32(req
, TCA_CAKE_FWMARK
, c
->fwmark
);
110 r
= sd_netlink_message_append_u32(req
, TCA_CAKE_WASH
, c
->wash
);
115 if (c
->split_gso
>= 0) {
116 r
= sd_netlink_message_append_u32(req
, TCA_CAKE_SPLIT_GSO
, c
->split_gso
);
121 r
= sd_netlink_message_close_container(req
);
128 int config_parse_cake_bandwidth(
130 const char *filename
,
133 unsigned section_line
,
140 _cleanup_(qdisc_free_or_set_invalidp
) QDisc
*qdisc
= NULL
;
141 CommonApplicationsKeptEnhanced
*c
;
142 Network
*network
= data
;
151 r
= qdisc_new_static(QDISC_KIND_CAKE
, network
, filename
, section_line
, &qdisc
);
155 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
156 "More than one kind of queueing discipline, ignoring assignment: %m");
162 if (isempty(rvalue
)) {
169 r
= parse_size(rvalue
, 1000, &k
);
171 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
172 "Failed to parse '%s=', ignoring assignment: %s",
183 int config_parse_cake_overhead(
185 const char *filename
,
188 unsigned section_line
,
195 _cleanup_(qdisc_free_or_set_invalidp
) QDisc
*qdisc
= NULL
;
196 CommonApplicationsKeptEnhanced
*c
;
197 Network
*network
= data
;
206 r
= qdisc_new_static(QDISC_KIND_CAKE
, network
, filename
, section_line
, &qdisc
);
210 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
211 "More than one kind of queueing discipline, ignoring assignment: %m");
217 if (isempty(rvalue
)) {
218 c
->overhead_set
= false;
223 r
= safe_atoi32(rvalue
, &v
);
225 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
226 "Failed to parse '%s=', ignoring assignment: %s",
230 if (v
< -64 || v
> 256) {
231 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
232 "Invalid '%s=', ignoring assignment: %s",
238 c
->overhead_set
= true;
243 int config_parse_cake_mpu(
245 const char *filename
,
248 unsigned section_line
,
255 _cleanup_(qdisc_free_or_set_invalidp
) QDisc
*qdisc
= NULL
;
256 CommonApplicationsKeptEnhanced
*c
;
257 Network
*network
= data
;
266 r
= qdisc_new_static(QDISC_KIND_CAKE
, network
, filename
, section_line
, &qdisc
);
270 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
271 "More than one kind of queueing discipline, ignoring assignment: %m");
277 if (isempty(rvalue
)) {
283 r
= safe_atou32(rvalue
, &v
);
285 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
286 "Failed to parse '%s=', ignoring assignment: %s",
290 if (v
<= 0 || v
> 256) {
291 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
292 "Invalid '%s=', ignoring assignment: %s",
302 int config_parse_cake_tristate(
304 const char *filename
,
307 unsigned section_line
,
314 _cleanup_(qdisc_free_or_set_invalidp
) QDisc
*qdisc
= NULL
;
315 CommonApplicationsKeptEnhanced
*c
;
316 Network
*network
= data
;
324 r
= qdisc_new_static(QDISC_KIND_CAKE
, network
, filename
, section_line
, &qdisc
);
328 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
329 "More than one kind of queueing discipline, ignoring assignment: %m");
335 if (streq(lvalue
, "AutoRateIngress"))
337 else if (streq(lvalue
, "UseRawPacketSize"))
339 else if (streq(lvalue
, "NAT"))
341 else if (streq(lvalue
, "Wash"))
343 else if (streq(lvalue
, "SplitGSO"))
344 dest
= &c
->split_gso
;
346 assert_not_reached();
348 if (isempty(rvalue
)) {
354 r
= parse_boolean(rvalue
);
356 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
357 "Failed to parse '%s=', ignoring assignment: %s",
367 static const char * const cake_compensation_mode_table
[_CAKE_COMPENSATION_MODE_MAX
] = {
368 [CAKE_COMPENSATION_MODE_NONE
] = "none",
369 [CAKE_COMPENSATION_MODE_ATM
] = "atm",
370 [CAKE_COMPENSATION_MODE_PTM
] = "ptm",
373 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(cake_compensation_mode
, CakeCompensationMode
);
375 int config_parse_cake_compensation_mode(
377 const char *filename
,
380 unsigned section_line
,
387 _cleanup_(qdisc_free_or_set_invalidp
) QDisc
*qdisc
= NULL
;
388 CommonApplicationsKeptEnhanced
*c
;
389 Network
*network
= data
;
390 CakeCompensationMode mode
;
398 r
= qdisc_new_static(QDISC_KIND_CAKE
, network
, filename
, section_line
, &qdisc
);
402 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
403 "More than one kind of queueing discipline, ignoring assignment: %m");
409 if (isempty(rvalue
)) {
410 c
->compensation_mode
= _CAKE_COMPENSATION_MODE_INVALID
;
415 mode
= cake_compensation_mode_from_string(rvalue
);
417 log_syntax(unit
, LOG_WARNING
, filename
, line
, mode
,
418 "Failed to parse '%s=', ignoring assignment: %s",
423 c
->compensation_mode
= mode
;
428 static const char * const cake_flow_isolation_mode_table
[_CAKE_FLOW_ISOLATION_MODE_MAX
] = {
429 [CAKE_FLOW_ISOLATION_MODE_NONE
] = "none",
430 [CAKE_FLOW_ISOLATION_MODE_SRC_IP
] = "src-host",
431 [CAKE_FLOW_ISOLATION_MODE_DST_IP
] = "dst-host",
432 [CAKE_FLOW_ISOLATION_MODE_HOSTS
] = "hosts",
433 [CAKE_FLOW_ISOLATION_MODE_FLOWS
] = "flows",
434 [CAKE_FLOW_ISOLATION_MODE_DUAL_SRC
] = "dual-src-host",
435 [CAKE_FLOW_ISOLATION_MODE_DUAL_DST
] = "dual-dst-host",
436 [CAKE_FLOW_ISOLATION_MODE_TRIPLE
] = "triple",
439 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(cake_flow_isolation_mode
, CakeFlowIsolationMode
);
441 int config_parse_cake_flow_isolation_mode(
443 const char *filename
,
446 unsigned section_line
,
453 _cleanup_(qdisc_free_or_set_invalidp
) QDisc
*qdisc
= NULL
;
454 CommonApplicationsKeptEnhanced
*c
;
455 Network
*network
= data
;
456 CakeFlowIsolationMode mode
;
464 r
= qdisc_new_static(QDISC_KIND_CAKE
, network
, filename
, section_line
, &qdisc
);
468 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
469 "More than one kind of queueing discipline, ignoring assignment: %m");
475 if (isempty(rvalue
)) {
476 c
->flow_isolation_mode
= _CAKE_FLOW_ISOLATION_MODE_INVALID
;
481 mode
= cake_flow_isolation_mode_from_string(rvalue
);
483 log_syntax(unit
, LOG_WARNING
, filename
, line
, mode
,
484 "Failed to parse '%s=', ignoring assignment: %s",
489 c
->flow_isolation_mode
= mode
;
494 static const char * const cake_priority_queueing_preset_table
[_CAKE_PRESET_MAX
] = {
495 [CAKE_PRESET_DIFFSERV3
] = "diffserv3",
496 [CAKE_PRESET_DIFFSERV4
] = "diffserv4",
497 [CAKE_PRESET_DIFFSERV8
] = "diffserv8",
498 [CAKE_PRESET_BESTEFFORT
] = "besteffort",
499 [CAKE_PRESET_PRECEDENCE
] = "precedence",
502 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(cake_priority_queueing_preset
, CakePriorityQueueingPreset
);
504 int config_parse_cake_priority_queueing_preset(
506 const char *filename
,
509 unsigned section_line
,
516 _cleanup_(qdisc_free_or_set_invalidp
) QDisc
*qdisc
= NULL
;
517 CommonApplicationsKeptEnhanced
*c
;
518 CakePriorityQueueingPreset preset
;
519 Network
*network
= data
;
527 r
= qdisc_new_static(QDISC_KIND_CAKE
, network
, filename
, section_line
, &qdisc
);
531 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
532 "More than one kind of queueing discipline, ignoring assignment: %m");
538 if (isempty(rvalue
)) {
539 c
->preset
= _CAKE_PRESET_INVALID
;
544 preset
= cake_priority_queueing_preset_from_string(rvalue
);
546 log_syntax(unit
, LOG_WARNING
, filename
, line
, preset
,
547 "Failed to parse '%s=', ignoring assignment: %s",
557 int config_parse_cake_fwmark(
559 const char *filename
,
562 unsigned section_line
,
569 _cleanup_(qdisc_free_or_set_invalidp
) QDisc
*qdisc
= NULL
;
570 CommonApplicationsKeptEnhanced
*c
;
571 Network
*network
= data
;
580 r
= qdisc_new_static(QDISC_KIND_CAKE
, network
, filename
, section_line
, &qdisc
);
584 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
585 "More than one kind of queueing discipline, ignoring assignment: %m");
591 if (isempty(rvalue
)) {
597 r
= safe_atou32(rvalue
, &fwmark
);
599 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
600 "Failed to parse '%s=', ignoring assignment: %s",
605 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
606 "Invalid '%s=', ignoring assignment: %s",
616 const QDiscVTable cake_vtable
= {
617 .object_size
= sizeof(CommonApplicationsKeptEnhanced
),
620 .fill_message
= cake_fill_message
,