libnl 1.1.4
sfq.c
1/*
2 * lib/route/sch/sfq.c SFQ Qdisc
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation version 2.1
7 * of the License.
8 *
9 * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
10 */
11
12/**
13 * @ingroup qdisc_api
14 * @defgroup sfq Stochastic Fairness Queueing (SFQ)
15 * @brief
16 *
17 * @par Parameter Description
18 * - \b Quantum: Number of bytes to send out per slot and round.
19 * - \b Perturbation: Timer period between changing the hash function.
20 * - \b Limit: Upper limit of queue in number of packets before SFQ starts
21 * dropping packets.
22 * - \b Divisor: Hash table divisor, i.e. size of hash table.
23 * @{
24 */
25
26#include <netlink-local.h>
27#include <netlink-tc.h>
28#include <netlink/netlink.h>
29#include <netlink/utils.h>
30#include <netlink/route/qdisc.h>
31#include <netlink/route/qdisc-modules.h>
32#include <netlink/route/sch/sfq.h>
33
34/** @cond SKIP */
35#define SCH_SFQ_ATTR_QUANTUM 0x01
36#define SCH_SFQ_ATTR_PERTURB 0x02
37#define SCH_SFQ_ATTR_LIMIT 0x04
38#define SCH_SFQ_ATTR_DIVISOR 0x08
39#define SCH_SFQ_ATTR_FLOWS 0x10
40/** @endcond */
41
42static inline struct rtnl_sfq *sfq_qdisc(struct rtnl_qdisc *qdisc)
43{
44 return (struct rtnl_sfq *) qdisc->q_subdata;
45}
46
47static inline struct rtnl_sfq *sfq_alloc(struct rtnl_qdisc *qdisc)
48{
49 if (!qdisc->q_subdata)
50 qdisc->q_subdata = calloc(1, sizeof(struct rtnl_sfq));
51
52 return sfq_qdisc(qdisc);
53}
54
55static int sfq_msg_parser(struct rtnl_qdisc *qdisc)
56{
57 struct rtnl_sfq *sfq;
58 struct tc_sfq_qopt *opts;
59
60 if (!(qdisc->ce_mask & TCA_ATTR_OPTS))
61 return 0;
62
63 if (qdisc->q_opts->d_size < sizeof(*opts))
64 return nl_error(EINVAL, "SFQ specific options size mismatch");
65
66 sfq = sfq_alloc(qdisc);
67 if (!sfq)
68 return nl_errno(ENOMEM);
69
70 opts = (struct tc_sfq_qopt *) qdisc->q_opts->d_data;
71
72 sfq->qs_quantum = opts->quantum;
73 sfq->qs_perturb = opts->perturb_period;
74 sfq->qs_limit = opts->limit;
75 sfq->qs_divisor = opts->divisor;
76 sfq->qs_flows = opts->flows;
77
78 sfq->qs_mask = (SCH_SFQ_ATTR_QUANTUM | SCH_SFQ_ATTR_PERTURB |
79 SCH_SFQ_ATTR_LIMIT | SCH_SFQ_ATTR_DIVISOR |
80 SCH_SFQ_ATTR_FLOWS);
81
82 return 0;
83}
84
85static void sfq_free_data(struct rtnl_qdisc *qdisc)
86{
87 free(qdisc->q_subdata);
88}
89
90static int sfq_dump_brief(struct rtnl_qdisc *qdisc, struct nl_dump_params *p,
91 int line)
92{
93 struct rtnl_sfq *sfq = sfq_qdisc(qdisc);
94
95 if (sfq)
96 dp_dump(p, " quantum %u perturb %us",
97 sfq->qs_quantum,
98 nl_ticks2us(sfq->qs_perturb * nl_get_hz()));
99
100 return line;
101}
102
103static int sfq_dump_full(struct rtnl_qdisc *qdisc, struct nl_dump_params *p,
104 int line)
105{
106 struct rtnl_sfq *sfq = sfq_qdisc(qdisc);
107
108 if (sfq)
109 dp_dump(p, "limit %u divisor %u",
110 sfq->qs_limit, sfq->qs_divisor);
111
112 return line;
113}
114
115static struct nl_msg *sfq_get_opts(struct rtnl_qdisc *qdisc)
116{
117 struct rtnl_sfq *sfq;
118 struct tc_sfq_qopt opts;
119 struct nl_msg *msg;
120
121 sfq = sfq_qdisc(qdisc);
122 if (!sfq)
123 return NULL;
124
125 msg = nlmsg_alloc();
126 if (!msg)
127 goto errout;
128
129 memset(&opts, 0, sizeof(opts));
130 opts.quantum = sfq->qs_quantum;
131 opts.perturb_period = sfq->qs_perturb;
132 opts.limit = sfq->qs_limit;
133
134 if (nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD) < 0)
135 goto errout;
136
137 return msg;
138errout:
139 nlmsg_free(msg);
140 return NULL;
141}
142
143/**
144 * @name Attribute Access
145 * @{
146 */
147
148/**
149 * Set quantum of SFQ qdisc.
150 * @arg qdisc SFQ qdisc to be modified.
151 * @arg quantum New quantum in bytes.
152 * @return 0 on success or a negative error code.
153 */
154int rtnl_sfq_set_quantum(struct rtnl_qdisc *qdisc, int quantum)
155{
156 struct rtnl_sfq *sfq;
157
158 sfq = sfq_alloc(qdisc);
159 if (!sfq)
160 return nl_errno(ENOMEM);
161
162 sfq->qs_quantum = quantum;
163 sfq->qs_mask |= SCH_SFQ_ATTR_QUANTUM;
164
165 return 0;
166}
167
168/**
169 * Get quantum of SFQ qdisc.
170 * @arg qdisc SFQ qdisc.
171 * @return Quantum in bytes or a negative error code.
172 */
173int rtnl_sfq_get_quantum(struct rtnl_qdisc *qdisc)
174{
175 struct rtnl_sfq *sfq;
176
177 sfq = sfq_qdisc(qdisc);
178 if (sfq && sfq->qs_mask & SCH_SFQ_ATTR_QUANTUM)
179 return sfq->qs_quantum;
180 else
181 return nl_errno(ENOENT);
182}
183
184/**
185 * Set limit of SFQ qdisc.
186 * @arg qdisc SFQ qdisc to be modified.
187 * @arg limit New limit in number of packets.
188 * @return 0 on success or a negative error code.
189 */
190int rtnl_sfq_set_limit(struct rtnl_qdisc *qdisc, int limit)
191{
192 struct rtnl_sfq *sfq;
193
194 sfq = sfq_alloc(qdisc);
195 if (!sfq)
196 return nl_errno(ENOMEM);
197
198 sfq->qs_limit = limit;
199 sfq->qs_mask |= SCH_SFQ_ATTR_LIMIT;
200
201 return 0;
202}
203
204/**
205 * Get limit of SFQ qdisc.
206 * @arg qdisc SFQ qdisc.
207 * @return Limit or a negative error code.
208 */
209int rtnl_sfq_get_limit(struct rtnl_qdisc *qdisc)
210{
211 struct rtnl_sfq *sfq;
212
213 sfq = sfq_qdisc(qdisc);
214 if (sfq && sfq->qs_mask & SCH_SFQ_ATTR_LIMIT)
215 return sfq->qs_limit;
216 else
217 return nl_errno(ENOENT);
218}
219
220/**
221 * Set perturbation interval of SFQ qdisc.
222 * @arg qdisc SFQ qdisc to be modified.
223 * @arg perturb New perturbation interval in seconds.
224 * @note A value of 0 disables perturbation altogether.
225 * @return 0 on success or a negative error code.
226 */
227int rtnl_sfq_set_perturb(struct rtnl_qdisc *qdisc, int perturb)
228{
229 struct rtnl_sfq *sfq;
230
231 sfq = sfq_alloc(qdisc);
232 if (!sfq)
233 return nl_errno(ENOMEM);
234
235 sfq->qs_perturb = perturb;
236 sfq->qs_mask |= SCH_SFQ_ATTR_PERTURB;
237
238 return 0;
239}
240
241/**
242 * Get perturbation interval of SFQ qdisc.
243 * @arg qdisc SFQ qdisc.
244 * @return Perturbation interval in seconds or a negative error code.
245 */
246int rtnl_sfq_get_perturb(struct rtnl_qdisc *qdisc)
247{
248 struct rtnl_sfq *sfq;
249
250 sfq = sfq_qdisc(qdisc);
251 if (sfq && sfq->qs_mask & SCH_SFQ_ATTR_PERTURB)
252 return sfq->qs_perturb;
253 else
254 return nl_errno(ENOENT);
255}
256
257/**
258 * Get divisor of SFQ qdisc.
259 * @arg qdisc SFQ qdisc.
260 * @return Divisor in number of entries or a negative error code.
261 */
262int rtnl_sfq_get_divisor(struct rtnl_qdisc *qdisc)
263{
264 struct rtnl_sfq *sfq;
265
266 sfq = sfq_qdisc(qdisc);
267 if (sfq && sfq->qs_mask & SCH_SFQ_ATTR_DIVISOR)
268 return sfq->qs_divisor;
269 else
270 return nl_errno(ENOENT);
271}
272
273/** @} */
274
275static struct rtnl_qdisc_ops sfq_ops = {
276 .qo_kind = "sfq",
277 .qo_msg_parser = sfq_msg_parser,
278 .qo_free_data = sfq_free_data,
279 .qo_dump[NL_DUMP_BRIEF] = sfq_dump_brief,
280 .qo_dump[NL_DUMP_FULL] = sfq_dump_full,
281 .qo_get_opts = sfq_get_opts,
282};
283
284static void __init sfq_init(void)
285{
286 rtnl_qdisc_register(&sfq_ops);
287}
288
289static void __exit sfq_exit(void)
290{
291 rtnl_qdisc_unregister(&sfq_ops);
292}
293
294/** @} */
void nlmsg_free(struct nl_msg *n)
Free a netlink message.
Definition: msg.c:656
struct nl_msg * nlmsg_alloc(void)
Allocate a new netlink message with the default maximum payload size.
Definition: msg.c:401
int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
Append data to tail of a netlink message.
Definition: msg.c:549
int rtnl_qdisc_unregister(struct rtnl_qdisc_ops *qops)
Unregister a qdisc module.
Definition: qdisc_api.c:61
int rtnl_qdisc_register(struct rtnl_qdisc_ops *qops)
Register a qdisc module.
Definition: qdisc_api.c:40
int rtnl_sfq_set_quantum(struct rtnl_qdisc *qdisc, int quantum)
Set quantum of SFQ qdisc.
Definition: sfq.c:154
int rtnl_sfq_get_quantum(struct rtnl_qdisc *qdisc)
Get quantum of SFQ qdisc.
Definition: sfq.c:173
int rtnl_sfq_get_divisor(struct rtnl_qdisc *qdisc)
Get divisor of SFQ qdisc.
Definition: sfq.c:262
int rtnl_sfq_get_perturb(struct rtnl_qdisc *qdisc)
Get perturbation interval of SFQ qdisc.
Definition: sfq.c:246
int rtnl_sfq_set_perturb(struct rtnl_qdisc *qdisc, int perturb)
Set perturbation interval of SFQ qdisc.
Definition: sfq.c:227
int rtnl_sfq_get_limit(struct rtnl_qdisc *qdisc)
Get limit of SFQ qdisc.
Definition: sfq.c:209
int rtnl_sfq_set_limit(struct rtnl_qdisc *qdisc, int limit)
Set limit of SFQ qdisc.
Definition: sfq.c:190
int nl_get_hz(void)
Return the value of HZ.
Definition: utils.c:428
uint32_t nl_ticks2us(uint32_t ticks)
Convert ticks to micro seconds.
Definition: utils.c:450
@ NL_DUMP_FULL
Dump all attributes but no statistics.
Definition: types.h:23
@ NL_DUMP_BRIEF
Dump object in a brief one-liner.
Definition: types.h:22
Dumping parameters.
Definition: types.h:37
Qdisc Operations.
Definition: qdisc-modules.h:26
char qo_kind[32]
Kind/Name of Qdisc.
Definition: qdisc-modules.h:30