1 /* SPDX-License-Identifier: LGPL-2.1-or-later
2 * Copyright © 2019 VMware, Inc. */
4 #include <linux/pkt_sched.h>
6 #include "sd-netlink.h"
10 #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_unref_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_unref_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_unref_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 r
= parse_tristate(rvalue
, &fqcd
->ecn
);
256 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
257 "Failed to parse '%s=', ignoring assignment: %s",
267 int config_parse_fair_queueing_controlled_delay_size(
269 const char *filename
,
272 unsigned section_line
,
279 _cleanup_(qdisc_unref_or_set_invalidp
) QDisc
*qdisc
= NULL
;
280 FairQueueingControlledDelay
*fqcd
;
281 Network
*network
= ASSERT_PTR(data
);
290 r
= qdisc_new_static(QDISC_KIND_FQ_CODEL
, network
, filename
, section_line
, &qdisc
);
294 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
295 "More than one kind of queueing discipline, ignoring assignment: %m");
299 fqcd
= FQ_CODEL(qdisc
);
301 if (STR_IN_SET(lvalue
, "MemoryLimitBytes", "MemoryLimit"))
302 p
= &fqcd
->memory_limit
;
303 else if (STR_IN_SET(lvalue
, "QuantumBytes", "Quantum"))
306 assert_not_reached();
308 if (isempty(rvalue
)) {
309 if (STR_IN_SET(lvalue
, "MemoryLimitBytes", "MemoryLimit"))
318 r
= parse_size(rvalue
, 1024, &sz
);
320 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
321 "Failed to parse '%s=', ignoring assignment: %s",
325 if (sz
>= UINT32_MAX
) {
326 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
327 "Specified '%s=' is too large, ignoring assignment: %s",
338 const QDiscVTable fq_codel_vtable
= {
339 .object_size
= sizeof(FairQueueingControlledDelay
),
340 .tca_kind
= "fq_codel",
341 .init
= fair_queueing_controlled_delay_init
,
342 .fill_message
= fair_queueing_controlled_delay_fill_message
,