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
;
28 static int cake_fill_message(Link
*link
, QDisc
*qdisc
, sd_netlink_message
*req
) {
29 CommonApplicationsKeptEnhanced
*c
;
38 r
= sd_netlink_message_open_container_union(req
, TCA_OPTIONS
, "cake");
40 return log_link_error_errno(link
, r
, "Could not open container TCA_OPTIONS: %m");
42 if (c
->bandwidth
> 0) {
43 r
= sd_netlink_message_append_u64(req
, TCA_CAKE_BASE_RATE64
, c
->bandwidth
);
45 return log_link_error_errno(link
, r
, "Could not append TCA_CAKE_BASE_RATE64 attribute: %m");
48 if (c
->autorate
>= 0) {
49 r
= sd_netlink_message_append_u32(req
, TCA_CAKE_AUTORATE
, c
->autorate
);
51 return log_link_error_errno(link
, r
, "Could not append TCA_CAKE_AUTORATE attribute: %m");
54 if (c
->overhead_set
) {
55 r
= sd_netlink_message_append_s32(req
, TCA_CAKE_OVERHEAD
, c
->overhead
);
57 return log_link_error_errno(link
, r
, "Could not append TCA_CAKE_OVERHEAD attribute: %m");
60 if (c
->compensation_mode
>= 0) {
61 r
= sd_netlink_message_append_u32(req
, TCA_CAKE_ATM
, c
->compensation_mode
);
63 return log_link_error_errno(link
, r
, "Could not append TCA_CAKE_ATM attribute: %m");
66 r
= sd_netlink_message_close_container(req
);
68 return log_link_error_errno(link
, r
, "Could not close container TCA_OPTIONS: %m");
73 int config_parse_cake_bandwidth(
78 unsigned section_line
,
85 _cleanup_(qdisc_free_or_set_invalidp
) QDisc
*qdisc
= NULL
;
86 CommonApplicationsKeptEnhanced
*c
;
87 Network
*network
= data
;
96 r
= qdisc_new_static(QDISC_KIND_CAKE
, network
, filename
, section_line
, &qdisc
);
100 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
101 "More than one kind of queueing discipline, ignoring assignment: %m");
107 if (isempty(rvalue
)) {
114 r
= parse_size(rvalue
, 1000, &k
);
116 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
117 "Failed to parse '%s=', ignoring assignment: %s",
128 int config_parse_cake_overhead(
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
)) {
163 c
->overhead_set
= false;
168 r
= safe_atoi32(rvalue
, &v
);
170 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
171 "Failed to parse '%s=', ignoring assignment: %s",
175 if (v
< -64 || v
> 256) {
176 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
177 "Invalid '%s=', ignoring assignment: %s",
183 c
->overhead_set
= true;
188 int config_parse_cake_tristate(
190 const char *filename
,
193 unsigned section_line
,
200 _cleanup_(qdisc_free_or_set_invalidp
) QDisc
*qdisc
= NULL
;
201 CommonApplicationsKeptEnhanced
*c
;
202 Network
*network
= data
;
210 r
= qdisc_new_static(QDISC_KIND_CAKE
, network
, filename
, section_line
, &qdisc
);
214 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
215 "More than one kind of queueing discipline, ignoring assignment: %m");
221 if (streq(lvalue
, "AutoRateIngress"))
224 assert_not_reached();
226 if (isempty(rvalue
)) {
232 r
= parse_boolean(rvalue
);
234 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
235 "Failed to parse '%s=', ignoring assignment: %s",
245 static const char * const cake_compensation_mode_table
[_CAKE_COMPENSATION_MODE_MAX
] = {
246 [CAKE_COMPENSATION_MODE_NONE
] = "none",
247 [CAKE_COMPENSATION_MODE_ATM
] = "atm",
248 [CAKE_COMPENSATION_MODE_PTM
] = "ptm",
251 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(cake_compensation_mode
, CakeCompensationMode
);
253 int config_parse_cake_compensation_mode(
255 const char *filename
,
258 unsigned section_line
,
265 _cleanup_(qdisc_free_or_set_invalidp
) QDisc
*qdisc
= NULL
;
266 CommonApplicationsKeptEnhanced
*c
;
267 Network
*network
= data
;
268 CakeCompensationMode mode
;
276 r
= qdisc_new_static(QDISC_KIND_CAKE
, network
, filename
, section_line
, &qdisc
);
280 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
281 "More than one kind of queueing discipline, ignoring assignment: %m");
287 if (isempty(rvalue
)) {
288 c
->compensation_mode
= _CAKE_COMPENSATION_MODE_INVALID
;
293 mode
= cake_compensation_mode_from_string(rvalue
);
295 log_syntax(unit
, LOG_WARNING
, filename
, line
, mode
,
296 "Failed to parse '%s=', ignoring assignment: %s",
301 c
->compensation_mode
= mode
;
306 const QDiscVTable cake_vtable
= {
307 .object_size
= sizeof(CommonApplicationsKeptEnhanced
),
310 .fill_message
= cake_fill_message
,