~ubuntu-branches/ubuntu/trusty/libnl3/trusty

« back to all changes in this revision

Viewing changes to lib/route/qdisc/sfq.c

  • Committer: Bazaar Package Importer
  • Author(s): Heiko Stuebner
  • Date: 2011-05-21 19:25:13 UTC
  • Revision ID: james.westby@ubuntu.com-20110521192513-1ieyu9w9kym4bt16
Tags: upstream-3.0
ImportĀ upstreamĀ versionĀ 3.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * lib/route/qdisc/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-2011 Thomas Graf <tgraf@suug.ch>
 
10
 */
 
11
 
 
12
/**
 
13
 * @ingroup qdisc
 
14
 * @defgroup qdisc_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/tc-api.h>
 
31
#include <netlink/route/qdisc.h>
 
32
#include <netlink/route/qdisc/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
 
 
42
static int sfq_msg_parser(struct rtnl_tc *tc, void *data)
 
43
{
 
44
        struct rtnl_sfq *sfq = data;
 
45
        struct tc_sfq_qopt *opts;
 
46
 
 
47
        if (!(tc->ce_mask & TCA_ATTR_OPTS))
 
48
                return 0;
 
49
 
 
50
        if (tc->tc_opts->d_size < sizeof(*opts))
 
51
                return -NLE_INVAL;
 
52
 
 
53
        opts = (struct tc_sfq_qopt *) tc->tc_opts->d_data;
 
54
 
 
55
        sfq->qs_quantum = opts->quantum;
 
56
        sfq->qs_perturb = opts->perturb_period;
 
57
        sfq->qs_limit = opts->limit;
 
58
        sfq->qs_divisor = opts->divisor;
 
59
        sfq->qs_flows = opts->flows;
 
60
 
 
61
        sfq->qs_mask = (SCH_SFQ_ATTR_QUANTUM | SCH_SFQ_ATTR_PERTURB |
 
62
                        SCH_SFQ_ATTR_LIMIT | SCH_SFQ_ATTR_DIVISOR |
 
63
                        SCH_SFQ_ATTR_FLOWS);
 
64
 
 
65
        return 0;
 
66
}
 
67
 
 
68
static void sfq_dump_line(struct rtnl_tc *tc, void *data,
 
69
                          struct nl_dump_params *p)
 
70
{
 
71
        struct rtnl_sfq *sfq = data;
 
72
 
 
73
        if (sfq)
 
74
                nl_dump(p, " quantum %u perturb %us", sfq->qs_quantum,
 
75
                        sfq->qs_perturb);
 
76
}
 
77
 
 
78
static void sfq_dump_details(struct rtnl_tc *tc, void *data,
 
79
                             struct nl_dump_params *p)
 
80
{
 
81
        struct rtnl_sfq *sfq = data;
 
82
 
 
83
        if (sfq)
 
84
                nl_dump(p, "limit %u divisor %u",
 
85
                        sfq->qs_limit, sfq->qs_divisor);
 
86
}
 
87
 
 
88
static int sfq_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
 
89
{
 
90
        struct rtnl_sfq *sfq = data;
 
91
        struct tc_sfq_qopt opts = {0};
 
92
 
 
93
        if (!sfq)
 
94
                BUG();
 
95
 
 
96
        opts.quantum = sfq->qs_quantum;
 
97
        opts.perturb_period = sfq->qs_perturb;
 
98
        opts.limit = sfq->qs_limit;
 
99
 
 
100
        return nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD);
 
101
}
 
102
 
 
103
/**
 
104
 * @name Attribute Access
 
105
 * @{
 
106
 */
 
107
 
 
108
/**
 
109
 * Set quantum of SFQ qdisc.
 
110
 * @arg qdisc           SFQ qdisc to be modified.
 
111
 * @arg quantum         New quantum in bytes.
 
112
 * @return 0 on success or a negative error code.
 
113
 */
 
114
void rtnl_sfq_set_quantum(struct rtnl_qdisc *qdisc, int quantum)
 
115
{
 
116
        struct rtnl_sfq *sfq;
 
117
        
 
118
        if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
 
119
                BUG();
 
120
 
 
121
        sfq->qs_quantum = quantum;
 
122
        sfq->qs_mask |= SCH_SFQ_ATTR_QUANTUM;
 
123
}
 
124
 
 
125
/**
 
126
 * Get quantum of SFQ qdisc.
 
127
 * @arg qdisc           SFQ qdisc.
 
128
 * @return Quantum in bytes or a negative error code.
 
129
 */
 
130
int rtnl_sfq_get_quantum(struct rtnl_qdisc *qdisc)
 
131
{
 
132
        struct rtnl_sfq *sfq;
 
133
        
 
134
        if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
 
135
                BUG();
 
136
 
 
137
        if (sfq->qs_mask & SCH_SFQ_ATTR_QUANTUM)
 
138
                return sfq->qs_quantum;
 
139
        else
 
140
                return -NLE_NOATTR;
 
141
}
 
142
 
 
143
/**
 
144
 * Set limit of SFQ qdisc.
 
145
 * @arg qdisc           SFQ qdisc to be modified.
 
146
 * @arg limit           New limit in number of packets.
 
147
 * @return 0 on success or a negative error code.
 
148
 */
 
149
void rtnl_sfq_set_limit(struct rtnl_qdisc *qdisc, int limit)
 
150
{
 
151
        struct rtnl_sfq *sfq;
 
152
        
 
153
        if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
 
154
                BUG();
 
155
 
 
156
        sfq->qs_limit = limit;
 
157
        sfq->qs_mask |= SCH_SFQ_ATTR_LIMIT;
 
158
}
 
159
 
 
160
/**
 
161
 * Get limit of SFQ qdisc.
 
162
 * @arg qdisc           SFQ qdisc.
 
163
 * @return Limit or a negative error code.
 
164
 */
 
165
int rtnl_sfq_get_limit(struct rtnl_qdisc *qdisc)
 
166
{
 
167
        struct rtnl_sfq *sfq;
 
168
        
 
169
        if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
 
170
                BUG();
 
171
 
 
172
        if (sfq->qs_mask & SCH_SFQ_ATTR_LIMIT)
 
173
                return sfq->qs_limit;
 
174
        else
 
175
                return -NLE_NOATTR;
 
176
}
 
177
 
 
178
/**
 
179
 * Set perturbation interval of SFQ qdisc.
 
180
 * @arg qdisc           SFQ qdisc to be modified.
 
181
 * @arg perturb         New perturbation interval in seconds.
 
182
 * @note A value of 0 disables perturbation altogether.
 
183
 * @return 0 on success or a negative error code.
 
184
 */
 
185
void rtnl_sfq_set_perturb(struct rtnl_qdisc *qdisc, int perturb)
 
186
{
 
187
        struct rtnl_sfq *sfq;
 
188
        
 
189
        if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
 
190
                BUG();
 
191
 
 
192
        sfq->qs_perturb = perturb;
 
193
        sfq->qs_mask |= SCH_SFQ_ATTR_PERTURB;
 
194
}
 
195
 
 
196
/**
 
197
 * Get perturbation interval of SFQ qdisc.
 
198
 * @arg qdisc           SFQ qdisc.
 
199
 * @return Perturbation interval in seconds or a negative error code.
 
200
 */
 
201
int rtnl_sfq_get_perturb(struct rtnl_qdisc *qdisc)
 
202
{
 
203
        struct rtnl_sfq *sfq;
 
204
        
 
205
        if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
 
206
                BUG();
 
207
 
 
208
        if (sfq->qs_mask & SCH_SFQ_ATTR_PERTURB)
 
209
                return sfq->qs_perturb;
 
210
        else
 
211
                return -NLE_NOATTR;
 
212
}
 
213
 
 
214
/**
 
215
 * Get divisor of SFQ qdisc.
 
216
 * @arg qdisc           SFQ qdisc.
 
217
 * @return Divisor in number of entries or a negative error code.
 
218
 */
 
219
int rtnl_sfq_get_divisor(struct rtnl_qdisc *qdisc)
 
220
{
 
221
        struct rtnl_sfq *sfq;
 
222
        
 
223
        if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
 
224
                BUG();
 
225
 
 
226
        if (sfq->qs_mask & SCH_SFQ_ATTR_DIVISOR)
 
227
                return sfq->qs_divisor;
 
228
        else
 
229
                return -NLE_NOATTR;
 
230
}
 
231
 
 
232
/** @} */
 
233
 
 
234
static struct rtnl_tc_ops sfq_ops = {
 
235
        .to_kind                = "sfq",
 
236
        .to_type                = RTNL_TC_TYPE_QDISC,
 
237
        .to_size                = sizeof(struct rtnl_sfq),
 
238
        .to_msg_parser          = sfq_msg_parser,
 
239
        .to_dump = {
 
240
            [NL_DUMP_LINE]      = sfq_dump_line,
 
241
            [NL_DUMP_DETAILS]   = sfq_dump_details,
 
242
        },
 
243
        .to_msg_fill            = sfq_msg_fill,
 
244
};
 
245
 
 
246
static void __init sfq_init(void)
 
247
{
 
248
        rtnl_tc_register(&sfq_ops);
 
249
}
 
250
 
 
251
static void __exit sfq_exit(void)
 
252
{
 
253
        rtnl_tc_unregister(&sfq_ops);
 
254
}
 
255
 
 
256
/** @} */