libnl: /data/src/libnl3/lib/route/qdisc/fq_codel.c Source File

libnl 3.10.0

fq_codel.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2013 Cong Wang <xiyou.wangcong@gmail.com>
4 */
5
6/**
7 * @ingroup qdisc
8 * @defgroup qdisc_fq_codel Fair Queue CoDel
9 * @brief
10 *
11 * @{
12 */
13
14#include "nl-default.h"
15
16#include <netlink/netlink.h>
17#include <netlink/route/qdisc.h>
18#include <netlink/route/qdisc/fq_codel.h>
19#include <netlink/utils.h>
20
21#include "tc-api.h"
22
23/** @cond SKIP */
24struct rtnl_fq_codel {
25 int fq_limit;
26 uint32_t fq_target;
27 uint32_t fq_interval;
28 int fq_flows;
29 uint32_t fq_quantum;
30 int fq_ecn;
31 uint32_t fq_mask;
32};
33
34#define SCH_FQ_CODEL_ATTR_TARGET 0x1
35#define SCH_FQ_CODEL_ATTR_LIMIT 0x2
36#define SCH_FQ_CODEL_ATTR_INTERVAL 0x4
37#define SCH_FQ_CODEL_ATTR_FLOWS 0x8
38#define SCH_FQ_CODEL_ATTR_QUANTUM 0x10
39#define SCH_FQ_CODEL_ATTR_ECN 0x20
40/** @endcond */
41
42static struct nla_policy fq_codel_policy[TCA_FQ_CODEL_MAX + 1] = {
43 [TCA_FQ_CODEL_TARGET] = { .type = NLA_U32 },
44 [TCA_FQ_CODEL_LIMIT] = { .type = NLA_U32 },
45 [TCA_FQ_CODEL_INTERVAL] = { .type = NLA_U32 },
46 [TCA_FQ_CODEL_ECN] = { .type = NLA_U32 },
47 [TCA_FQ_CODEL_FLOWS] = { .type = NLA_U32 },
48 [TCA_FQ_CODEL_QUANTUM] = { .type = NLA_U32 },
49};
50
51static int fq_codel_msg_parser(struct rtnl_tc *tc, void *data)
52{
53 struct rtnl_fq_codel *fq_codel = data;
54 struct nlattr *tb[TCA_FQ_CODEL_MAX + 1];
55 int err;
56
57 err = tca_parse(tb, TCA_FQ_CODEL_MAX, tc, fq_codel_policy);
58 if (err < 0)
59 return err;
60
61 if (tb[TCA_FQ_CODEL_TARGET]) {
62 fq_codel->fq_target = nla_get_u32(tb[TCA_FQ_CODEL_TARGET]);
63 fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_TARGET;
64 }
65
66 if (tb[TCA_FQ_CODEL_INTERVAL]) {
67 fq_codel->fq_interval = nla_get_u32(tb[TCA_FQ_CODEL_INTERVAL]);
68 fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_INTERVAL;
69 }
70
71 if (tb[TCA_FQ_CODEL_LIMIT]) {
72 fq_codel->fq_limit = nla_get_u32(tb[TCA_FQ_CODEL_LIMIT]);
73 fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_LIMIT;
74 }
75
76 if (tb[TCA_FQ_CODEL_QUANTUM]) {
77 fq_codel->fq_quantum = nla_get_u32(tb[TCA_FQ_CODEL_QUANTUM]);
78 fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_QUANTUM;
79 }
80
81 if (tb[TCA_FQ_CODEL_FLOWS]) {
82 fq_codel->fq_flows = nla_get_u32(tb[TCA_FQ_CODEL_FLOWS]);
83 fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_FLOWS;
84 }
85
86 if (tb[TCA_FQ_CODEL_ECN]) {
87 fq_codel->fq_ecn = nla_get_u32(tb[TCA_FQ_CODEL_ECN]);
88 fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_ECN;
89 }
90
91 return 0;
92}
93
94static void fq_codel_dump_line(struct rtnl_tc *tc, void *data,
95 struct nl_dump_params *p)
96{
97 struct rtnl_fq_codel *fq_codel = data;
98
99 if (!fq_codel)
100 return;
101
102 if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_LIMIT)
103 nl_dump(p, " limit %u packets", fq_codel->fq_limit);
104 if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_TARGET)
105 nl_dump(p, " target %u", fq_codel->fq_target);
106 if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_INTERVAL)
107 nl_dump(p, " interval %u", fq_codel->fq_interval);
108 if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_ECN)
109 nl_dump(p, " ecn %u", fq_codel->fq_ecn);
110 if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_FLOWS)
111 nl_dump(p, " flows %u", fq_codel->fq_flows);
112 if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_QUANTUM)
113 nl_dump(p, " quantum %u", fq_codel->fq_quantum);
114}
115
116static int fq_codel_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
117{
118 struct rtnl_fq_codel *fq_codel = data;
119
120 if (!fq_codel)
121 return -NLE_INVAL;
122
123 if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_LIMIT)
124 NLA_PUT_U32(msg, TCA_FQ_CODEL_LIMIT, fq_codel->fq_limit);
125 if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_INTERVAL)
126 NLA_PUT_U32(msg, TCA_FQ_CODEL_INTERVAL, fq_codel->fq_interval);
127 if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_TARGET)
128 NLA_PUT_U32(msg, TCA_FQ_CODEL_TARGET, fq_codel->fq_target);
129 if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_QUANTUM)
130 NLA_PUT_U32(msg, TCA_FQ_CODEL_QUANTUM, fq_codel->fq_quantum);
131 if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_FLOWS)
132 NLA_PUT_U32(msg, TCA_FQ_CODEL_FLOWS, fq_codel->fq_flows);
133 if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_ECN)
134 NLA_PUT_U32(msg, TCA_FQ_CODEL_ECN, fq_codel->fq_ecn);
135 return 0;
136
137nla_put_failure:
138 return -NLE_MSGSIZE;
139
140}
141
142/**
143 * @name Attribute Modification
144 * @{
145 */
146
147/**
148 * Set limit of fq_codel qdisc.
149 * @arg qdisc fq_codel qdisc to be modified.
150 * @arg limit New limit.
151 * @return 0 on success or a negative error code.
152 */
153 int rtnl_qdisc_fq_codel_set_limit(struct rtnl_qdisc *qdisc, int limit)
154{
155 struct rtnl_fq_codel *fq_codel;
156
157 if (!(fq_codel = rtnl_tc_data(TC_CAST(qdisc))))
158 return -NLE_NOMEM;
159
160 fq_codel->fq_limit = limit;
161 fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_LIMIT;
162
163 return 0;
164}
165
166/**
167 * Get limit of a fq_codel qdisc.
168 * @arg qdisc fq_codel qdisc.
169 * @return Numeric limit or a negative error code.
170 */
171 int rtnl_qdisc_fq_codel_get_limit(struct rtnl_qdisc *qdisc)
172{
173 struct rtnl_fq_codel *fq_codel;
174
175 if (!(fq_codel = rtnl_tc_data(TC_CAST(qdisc))))
176 return -NLE_NOMEM;
177
178 if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_LIMIT)
179 return fq_codel->fq_limit;
180 else
181 return -NLE_NOATTR;
182}
183
184/**
185 * Set target of fq_codel qdisc.
186 * @arg qdisc fq_codel qdisc to be modified.
187 * @arg target New target.
188 * @return 0 on success or a negative error code.
189 */
190 int rtnl_qdisc_fq_codel_set_target(struct rtnl_qdisc *qdisc, uint32_t target)
191{
192 struct rtnl_fq_codel *fq_codel;
193
194 if (!(fq_codel = rtnl_tc_data(TC_CAST(qdisc))))
195 return -NLE_NOMEM;
196
197 fq_codel->fq_target = target;
198 fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_TARGET;
199
200 return 0;
201}
202
203/**
204 * Get target of a fq_codel qdisc.
205 * @arg qdisc fq_codel qdisc.
206 * @return Numeric target or zero.
207 */
208uint32_t rtnl_qdisc_fq_codel_get_target(struct rtnl_qdisc *qdisc)
209{
210 struct rtnl_fq_codel *fq_codel;
211
212 if ((fq_codel = rtnl_tc_data(TC_CAST(qdisc))) &&
213 fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_TARGET)
214 return fq_codel->fq_target;
215 else
216 return 0;
217}
218
219/**
220 * Set interval of fq_codel qdisc.
221 * @arg qdisc fq_codel qdisc to be modified.
222 * @arg interval New interval.
223 * @return 0 on success or a negative error code.
224 */
225 int rtnl_qdisc_fq_codel_set_interval(struct rtnl_qdisc *qdisc, uint32_t interval)
226{
227 struct rtnl_fq_codel *fq_codel;
228
229 if (!(fq_codel = rtnl_tc_data(TC_CAST(qdisc))))
230 return -NLE_NOMEM;
231
232 fq_codel->fq_interval = interval;
233 fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_INTERVAL;
234
235 return 0;
236}
237
238/**
239 * Get target of a fq_codel qdisc.
240 * @arg qdisc fq_codel qdisc.
241 * @return Numeric interval or zero.
242 */
243uint32_t rtnl_qdisc_fq_codel_get_interval(struct rtnl_qdisc *qdisc)
244{
245 struct rtnl_fq_codel *fq_codel;
246
247 if ((fq_codel = rtnl_tc_data(TC_CAST(qdisc))) &&
248 fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_INTERVAL)
249 return fq_codel->fq_interval;
250 else
251 return 0;
252}
253
254/**
255 * Set quantum of fq_codel qdisc.
256 * @arg qdisc fq_codel qdisc to be modified.
257 * @arg quantum New quantum.
258 * @return 0 on success or a negative error code.
259 */
260 int rtnl_qdisc_fq_codel_set_quantum(struct rtnl_qdisc *qdisc, uint32_t quantum)
261{
262 struct rtnl_fq_codel *fq_codel;
263
264 if (!(fq_codel = rtnl_tc_data(TC_CAST(qdisc))))
265 return -NLE_NOMEM;
266
267 fq_codel->fq_quantum = quantum;
268 fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_QUANTUM;
269
270 return 0;
271}
272
273/**
274 * Get quantum of a fq_codel qdisc.
275 * @arg qdisc fq_codel qdisc.
276 * @return Numeric quantum or zero.
277 */
278uint32_t rtnl_qdisc_fq_codel_get_quantum(struct rtnl_qdisc *qdisc)
279{
280 struct rtnl_fq_codel *fq_codel;
281
282 if ((fq_codel = rtnl_tc_data(TC_CAST(qdisc))) &&
283 (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_QUANTUM))
284 return fq_codel->fq_quantum;
285 else
286 return 0;
287}
288
289/**
290 * Set flows of fq_codel qdisc.
291 * @arg qdisc fq_codel qdisc to be modified.
292 * @arg flows New flows value.
293 * @return 0 on success or a negative error code.
294 */
295 int rtnl_qdisc_fq_codel_set_flows(struct rtnl_qdisc *qdisc, int flows)
296{
297 struct rtnl_fq_codel *fq_codel;
298
299 if (!(fq_codel = rtnl_tc_data(TC_CAST(qdisc))))
300 return -NLE_NOMEM;
301
302 fq_codel->fq_flows = flows;
303 fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_FLOWS;
304
305 return 0;
306}
307
308/**
309 * Get flows of a fq_codel qdisc.
310 * @arg qdisc fq_codel qdisc.
311 * @return Numeric flows or a negative error code.
312 */
313 int rtnl_qdisc_fq_codel_get_flows(struct rtnl_qdisc *qdisc)
314{
315 struct rtnl_fq_codel *fq_codel;
316
317 if (!(fq_codel = rtnl_tc_data(TC_CAST(qdisc))))
318 return -NLE_NOMEM;
319
320 if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_FLOWS)
321 return fq_codel->fq_flows;
322 else
323 return -NLE_NOATTR;
324}
325/**
326 * Set ecn of fq_codel qdisc.
327 * @arg qdisc fq_codel qdisc to be modified.
328 * @arg ecn New ecn value.
329 * @return 0 on success or a negative error code.
330 */
331 int rtnl_qdisc_fq_codel_set_ecn(struct rtnl_qdisc *qdisc, int ecn)
332{
333 struct rtnl_fq_codel *fq_codel;
334
335 if (!(fq_codel = rtnl_tc_data(TC_CAST(qdisc))))
336 return -NLE_NOMEM;
337
338 fq_codel->fq_ecn = ecn;
339 fq_codel->fq_mask |= SCH_FQ_CODEL_ATTR_ECN;
340
341 return 0;
342}
343
344/**
345 * Get ecn of a fq_codel qdisc.
346 * @arg qdisc fq_codel qdisc.
347 * @return Numeric ecn or a negative error code.
348 */
349 int rtnl_qdisc_fq_codel_get_ecn(struct rtnl_qdisc *qdisc)
350{
351 struct rtnl_fq_codel *fq_codel;
352
353 if (!(fq_codel = rtnl_tc_data(TC_CAST(qdisc))))
354 return -NLE_NOMEM;
355
356 if (fq_codel->fq_mask & SCH_FQ_CODEL_ATTR_ECN)
357 return fq_codel->fq_ecn;
358 else
359 return -NLE_NOATTR;
360}
361/** @} */
362
363static struct rtnl_tc_ops fq_codel_ops = {
364 .to_kind = "fq_codel",
365 .to_type = RTNL_TC_TYPE_QDISC,
366 .to_size = sizeof(struct rtnl_fq_codel),
367 .to_msg_parser = fq_codel_msg_parser,
368 .to_dump[NL_DUMP_LINE] = fq_codel_dump_line,
369 .to_msg_fill = fq_codel_msg_fill,
370};
371
372static void _nl_init fq_codel_init(void)
373{
374 rtnl_tc_register(&fq_codel_ops);
375}
376
377static void _nl_exit fq_codel_exit(void)
378{
379 rtnl_tc_unregister(&fq_codel_ops);
380}
381
382/** @} */
nla_get_u32
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition attr.c:712
NLA_PUT_U32
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition attr.h:230
NLA_U32
@ NLA_U32
32 bit integer
Definition attr.h:37
rtnl_qdisc_fq_codel_get_ecn
int rtnl_qdisc_fq_codel_get_ecn(struct rtnl_qdisc *qdisc)
Get ecn of a fq_codel qdisc.
Definition fq_codel.c:349
rtnl_qdisc_fq_codel_get_flows
int rtnl_qdisc_fq_codel_get_flows(struct rtnl_qdisc *qdisc)
Get flows of a fq_codel qdisc.
Definition fq_codel.c:313
rtnl_qdisc_fq_codel_set_target
int rtnl_qdisc_fq_codel_set_target(struct rtnl_qdisc *qdisc, uint32_t target)
Set target of fq_codel qdisc.
Definition fq_codel.c:190
rtnl_qdisc_fq_codel_get_target
uint32_t rtnl_qdisc_fq_codel_get_target(struct rtnl_qdisc *qdisc)
Get target of a fq_codel qdisc.
Definition fq_codel.c:208
rtnl_qdisc_fq_codel_set_interval
int rtnl_qdisc_fq_codel_set_interval(struct rtnl_qdisc *qdisc, uint32_t interval)
Set interval of fq_codel qdisc.
Definition fq_codel.c:225
rtnl_qdisc_fq_codel_set_flows
int rtnl_qdisc_fq_codel_set_flows(struct rtnl_qdisc *qdisc, int flows)
Set flows of fq_codel qdisc.
Definition fq_codel.c:295
rtnl_qdisc_fq_codel_set_quantum
int rtnl_qdisc_fq_codel_set_quantum(struct rtnl_qdisc *qdisc, uint32_t quantum)
Set quantum of fq_codel qdisc.
Definition fq_codel.c:260
rtnl_qdisc_fq_codel_get_quantum
uint32_t rtnl_qdisc_fq_codel_get_quantum(struct rtnl_qdisc *qdisc)
Get quantum of a fq_codel qdisc.
Definition fq_codel.c:278
rtnl_qdisc_fq_codel_set_ecn
int rtnl_qdisc_fq_codel_set_ecn(struct rtnl_qdisc *qdisc, int ecn)
Set ecn of fq_codel qdisc.
Definition fq_codel.c:331
rtnl_qdisc_fq_codel_set_limit
int rtnl_qdisc_fq_codel_set_limit(struct rtnl_qdisc *qdisc, int limit)
Set limit of fq_codel qdisc.
Definition fq_codel.c:153
rtnl_qdisc_fq_codel_get_interval
uint32_t rtnl_qdisc_fq_codel_get_interval(struct rtnl_qdisc *qdisc)
Get target of a fq_codel qdisc.
Definition fq_codel.c:243
rtnl_qdisc_fq_codel_get_limit
int rtnl_qdisc_fq_codel_get_limit(struct rtnl_qdisc *qdisc)
Get limit of a fq_codel qdisc.
Definition fq_codel.c:171
TC_CAST
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
Definition tc.h:50
rtnl_tc_data
void * rtnl_tc_data(struct rtnl_tc *)
Return pointer to private data of traffic control object.
Definition tc.c:1079
rtnl_tc_register
int rtnl_tc_register(struct rtnl_tc_ops *)
Register a traffic control module.
Definition tc.c:1018
rtnl_tc_unregister
void rtnl_tc_unregister(struct rtnl_tc_ops *)
Unregister a traffic control module.
Definition tc.c:1052
nl_dump
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition utils.c:1015
NL_DUMP_LINE
@ NL_DUMP_LINE
Dump object briefly on one line.
Definition types.h:20
nl_dump_params
Dumping parameters.
Definition types.h:32
nla_policy
Attribute validation policy.
Definition attr.h:63
nla_policy::type
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition attr.h:65
rtnl_qdisc
Definition nl-route.h:118
rtnl_tc
Definition nl-route.h:114