1 /* SPDX-License-Identifier: LGPL-2.1-or-later
2 * Copyright © 2019 VMware, Inc. */
4 #include <linux/pkt_sched.h>
6 #include "alloc-util.h"
7 #include "conf-parser.h"
8 #include "netlink-util.h"
9 #include "parse-util.h"
11 #include "string-util.h"
14 static int fair_queueing_controlled_delay_init(QDisc
*qdisc
) {
15 FairQueueingControlledDelay
*fqcd
;
19 fqcd
= FQ_CODEL(qdisc
);
21 fqcd
->memory_limit
= UINT32_MAX
;
22 fqcd
->ce_threshold_usec
= USEC_INFINITY
;
28 static int fair_queueing_controlled_delay_fill_message(Link
*link
, QDisc
*qdisc
, sd_netlink_message
*req
) {
29 FairQueueingControlledDelay
*fqcd
;
36 assert_se(fqcd
= FQ_CODEL(qdisc
));
38 r
= sd_netlink_message_open_container_union(req
, TCA_OPTIONS
, "fq_codel");
42 if (fqcd
->packet_limit
> 0) {
43 r
= sd_netlink_message_append_u32(req
, TCA_FQ_CODEL_LIMIT
, fqcd
->packet_limit
);
48 if (fqcd
->flows
> 0) {
49 r
= sd_netlink_message_append_u32(req
, TCA_FQ_CODEL_FLOWS
, fqcd
->flows
);
54 if (fqcd
->quantum
> 0) {
55 r
= sd_netlink_message_append_u32(req
, TCA_FQ_CODEL_QUANTUM
, fqcd
->quantum
);
60 if (fqcd
->interval_usec
> 0) {
61 r
= sd_netlink_message_append_u32(req
, TCA_FQ_CODEL_INTERVAL
, fqcd
->interval_usec
);
66 if (fqcd
->target_usec
> 0) {
67 r
= sd_netlink_message_append_u32(req
, TCA_FQ_CODEL_TARGET
, fqcd
->target_usec
);
73 r
= sd_netlink_message_append_u32(req
, TCA_FQ_CODEL_ECN
, fqcd
->ecn
);
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
);
84 if (fqcd
->memory_limit
!= UINT32_MAX
) {
85 r
= sd_netlink_message_append_u32(req
, TCA_FQ_CODEL_MEMORY_LIMIT
, fqcd
->memory_limit
);
90 r
= sd_netlink_message_close_container(req
);
97 int config_parse_fair_queueing_controlled_delay_u32(
102 unsigned section_line
,
109 _cleanup_(qdisc_free_or_set_invalidp
) QDisc
*qdisc
= NULL
;
110 FairQueueingControlledDelay
*fqcd
;
111 Network
*network
= ASSERT_PTR(data
);
119 r
= qdisc_new_static(QDISC_KIND_FQ_CODEL
, network
, filename
, section_line
, &qdisc
);
123 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
124 "More than one kind of queueing discipline, ignoring assignment: %m");
128 fqcd
= FQ_CODEL(qdisc
);
130 if (streq(lvalue
, "PacketLimit"))
131 p
= &fqcd
->packet_limit
;
132 else if (streq(lvalue
, "Flows"))
135 assert_not_reached();
137 if (isempty(rvalue
)) {
144 r
= safe_atou32(rvalue
, p
);
146 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
147 "Failed to parse '%s=', ignoring assignment: %s",
157 int config_parse_fair_queueing_controlled_delay_usec(
159 const char *filename
,
162 unsigned section_line
,
169 _cleanup_(qdisc_free_or_set_invalidp
) QDisc
*qdisc
= NULL
;
170 FairQueueingControlledDelay
*fqcd
;
171 Network
*network
= ASSERT_PTR(data
);
179 r
= qdisc_new_static(QDISC_KIND_FQ_CODEL
, network
, filename
, section_line
, &qdisc
);
183 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
184 "More than one kind of queueing discipline, ignoring assignment: %m");
188 fqcd
= FQ_CODEL(qdisc
);
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
;
197 assert_not_reached();
199 if (isempty(rvalue
)) {
200 if (streq(lvalue
, "CEThresholdSec"))
209 r
= parse_sec(rvalue
, p
);
211 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
212 "Failed to parse '%s=', ignoring assignment: %s",
222 int config_parse_fair_queueing_controlled_delay_bool(
224 const char *filename
,
227 unsigned section_line
,
234 _cleanup_(qdisc_free_or_set_invalidp
) QDisc
*qdisc
= NULL
;
235 FairQueueingControlledDelay
*fqcd
;
236 Network
*network
= ASSERT_PTR(data
);
243 r
= qdisc_new_static(QDISC_KIND_FQ_CODEL
, network
, filename
, section_line
, &qdisc
);
247 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
248 "More than one kind of queueing discipline, ignoring assignment: %m");
252 fqcd
= FQ_CODEL(qdisc
);
254 if (isempty(rvalue
)) {
261 r
= parse_boolean(rvalue
);
263 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
264 "Failed to parse '%s=', ignoring assignment: %s",
275 int config_parse_fair_queueing_controlled_delay_size(
277 const char *filename
,
280 unsigned section_line
,
287 _cleanup_(qdisc_free_or_set_invalidp
) QDisc
*qdisc
= NULL
;
288 FairQueueingControlledDelay
*fqcd
;
289 Network
*network
= ASSERT_PTR(data
);
298 r
= qdisc_new_static(QDISC_KIND_FQ_CODEL
, network
, filename
, section_line
, &qdisc
);
302 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
303 "More than one kind of queueing discipline, ignoring assignment: %m");
307 fqcd
= FQ_CODEL(qdisc
);
309 if (STR_IN_SET(lvalue
, "MemoryLimitBytes", "MemoryLimit"))
310 p
= &fqcd
->memory_limit
;
311 else if (STR_IN_SET(lvalue
, "QuantumBytes", "Quantum"))
314 assert_not_reached();
316 if (isempty(rvalue
)) {
317 if (STR_IN_SET(lvalue
, "MemoryLimitBytes", "MemoryLimit"))
326 r
= parse_size(rvalue
, 1024, &sz
);
328 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
329 "Failed to parse '%s=', ignoring assignment: %s",
333 if (sz
>= UINT32_MAX
) {
334 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
335 "Specified '%s=' is too large, ignoring assignment: %s",
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
,