1 /* SPDX-License-Identifier: LGPL-2.1+
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"
13 static int fair_queueing_controlled_delay_init(QDisc
*qdisc
) {
14 FairQueueingControlledDelay
*fqcd
;
18 fqcd
= FQ_CODEL(qdisc
);
20 fqcd
->memory_limit
= UINT32_MAX
;
21 fqcd
->ce_threshold_usec
= USEC_INFINITY
;
27 static int fair_queueing_controlled_delay_fill_message(Link
*link
, QDisc
*qdisc
, sd_netlink_message
*req
) {
28 FairQueueingControlledDelay
*fqcd
;
35 fqcd
= FQ_CODEL(qdisc
);
37 r
= sd_netlink_message_open_container_union(req
, TCA_OPTIONS
, "fq_codel");
39 return log_link_error_errno(link
, r
, "Could not open container TCA_OPTIONS: %m");
41 if (fqcd
->packet_limit
> 0) {
42 r
= sd_netlink_message_append_u32(req
, TCA_FQ_CODEL_LIMIT
, fqcd
->packet_limit
);
44 return log_link_error_errno(link
, r
, "Could not append TCA_FQ_CODEL_LIMIT attribute: %m");
47 if (fqcd
->flows
> 0) {
48 r
= sd_netlink_message_append_u32(req
, TCA_FQ_CODEL_FLOWS
, fqcd
->flows
);
50 return log_link_error_errno(link
, r
, "Could not append TCA_FQ_CODEL_FLOWS attribute: %m");
53 if (fqcd
->quantum
> 0) {
54 r
= sd_netlink_message_append_u32(req
, TCA_FQ_CODEL_QUANTUM
, fqcd
->quantum
);
56 return log_link_error_errno(link
, r
, "Could not append TCA_FQ_CODEL_QUANTUM attribute: %m");
59 if (fqcd
->interval_usec
> 0) {
60 r
= sd_netlink_message_append_u32(req
, TCA_FQ_CODEL_INTERVAL
, fqcd
->interval_usec
);
62 return log_link_error_errno(link
, r
, "Could not append TCA_FQ_CODEL_INTERVAL attribute: %m");
65 if (fqcd
->target_usec
> 0) {
66 r
= sd_netlink_message_append_u32(req
, TCA_FQ_CODEL_TARGET
, fqcd
->target_usec
);
68 return log_link_error_errno(link
, r
, "Could not append TCA_FQ_CODEL_TARGET attribute: %m");
72 r
= sd_netlink_message_append_u32(req
, TCA_FQ_CODEL_ECN
, fqcd
->ecn
);
74 return log_link_error_errno(link
, r
, "Could not append TCA_FQ_CODEL_ECN attribute: %m");
77 if (fqcd
->ce_threshold_usec
!= USEC_INFINITY
) {
78 r
= sd_netlink_message_append_u32(req
, TCA_FQ_CODEL_CE_THRESHOLD
, fqcd
->ce_threshold_usec
);
80 return log_link_error_errno(link
, r
, "Could not append TCA_FQ_CODEL_CE_THRESHOLD attribute: %m");
83 if (fqcd
->memory_limit
!= UINT32_MAX
) {
84 r
= sd_netlink_message_append_u32(req
, TCA_FQ_CODEL_MEMORY_LIMIT
, fqcd
->memory_limit
);
86 return log_link_error_errno(link
, r
, "Could not append TCA_FQ_CODEL_MEMORY_LIMIT attribute: %m");
89 r
= sd_netlink_message_close_container(req
);
91 return log_link_error_errno(link
, r
, "Could not close container TCA_OPTIONS: %m");
96 int config_parse_fair_queueing_controlled_delay_u32(
101 unsigned section_line
,
108 _cleanup_(qdisc_free_or_set_invalidp
) QDisc
*qdisc
= NULL
;
109 FairQueueingControlledDelay
*fqcd
;
110 Network
*network
= data
;
119 r
= qdisc_new_static(QDISC_KIND_FQ_CODEL
, network
, filename
, section_line
, &qdisc
);
123 return log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
124 "More than one kind of queueing discipline, ignoring assignment: %m");
126 fqcd
= FQ_CODEL(qdisc
);
128 if (streq(lvalue
, "PacketLimit"))
129 p
= &fqcd
->packet_limit
;
130 else if (streq(lvalue
, "Flows"))
133 assert_not_reached("Invalid lvalue.");
135 if (isempty(rvalue
)) {
142 r
= safe_atou32(rvalue
, p
);
144 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
145 "Failed to parse '%s=', ignoring assignment: %s",
155 int config_parse_fair_queueing_controlled_delay_usec(
157 const char *filename
,
160 unsigned section_line
,
167 _cleanup_(qdisc_free_or_set_invalidp
) QDisc
*qdisc
= NULL
;
168 FairQueueingControlledDelay
*fqcd
;
169 Network
*network
= data
;
178 r
= qdisc_new_static(QDISC_KIND_FQ_CODEL
, network
, filename
, section_line
, &qdisc
);
182 return log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
183 "More than one kind of queueing discipline, ignoring assignment: %m");
185 fqcd
= FQ_CODEL(qdisc
);
187 if (streq(lvalue
, "TargetSec"))
188 p
= &fqcd
->target_usec
;
189 else if (streq(lvalue
, "IntervalSec"))
190 p
= &fqcd
->interval_usec
;
191 else if (streq(lvalue
, "CEThresholdSec"))
192 p
= &fqcd
->ce_threshold_usec
;
194 assert_not_reached("Invalid lvalue.");
196 if (isempty(rvalue
)) {
197 if (streq(lvalue
, "CEThresholdSec"))
206 r
= parse_sec(rvalue
, p
);
208 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
209 "Failed to parse '%s=', ignoring assignment: %s",
219 int config_parse_fair_queueing_controlled_delay_bool(
221 const char *filename
,
224 unsigned section_line
,
231 _cleanup_(qdisc_free_or_set_invalidp
) QDisc
*qdisc
= NULL
;
232 FairQueueingControlledDelay
*fqcd
;
233 Network
*network
= data
;
241 r
= qdisc_new_static(QDISC_KIND_FQ_CODEL
, network
, filename
, section_line
, &qdisc
);
245 return log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
246 "More than one kind of queueing discipline, ignoring assignment: %m");
248 fqcd
= FQ_CODEL(qdisc
);
250 if (isempty(rvalue
)) {
257 r
= parse_boolean(rvalue
);
259 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
260 "Failed to parse '%s=', ignoring assignment: %s",
271 int config_parse_fair_queueing_controlled_delay_size(
273 const char *filename
,
276 unsigned section_line
,
283 _cleanup_(qdisc_free_or_set_invalidp
) QDisc
*qdisc
= NULL
;
284 FairQueueingControlledDelay
*fqcd
;
285 Network
*network
= data
;
295 r
= qdisc_new_static(QDISC_KIND_FQ_CODEL
, network
, filename
, section_line
, &qdisc
);
299 return log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
300 "More than one kind of queueing discipline, ignoring assignment: %m");
302 fqcd
= FQ_CODEL(qdisc
);
304 if (streq(lvalue
, "MemoryLimit"))
305 p
= &fqcd
->memory_limit
;
306 else if (streq(lvalue
, "Quantum"))
309 assert_not_reached("Invalid lvalue.");
311 if (isempty(rvalue
)) {
312 if (streq(lvalue
, "MemoryLimit"))
321 r
= parse_size(rvalue
, 1024, &sz
);
323 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
324 "Failed to parse '%s=', ignoring assignment: %s",
328 if (sz
>= UINT32_MAX
) {
329 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
330 "Specified '%s=' is too large, ignoring assignment: %s",
341 const QDiscVTable fq_codel_vtable
= {
342 .object_size
= sizeof(FairQueueingControlledDelay
),
343 .tca_kind
= "fq_codel",
344 .init
= fair_queueing_controlled_delay_init
,
345 .fill_message
= fair_queueing_controlled_delay_fill_message
,