Blame view
net/sched/sch_dsmark.c
11.1 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 |
/* net/sched/sch_dsmark.c - Differentiated Services field marker */ /* Written 1998-2000 by Werner Almesberger, EPFL ICA */ |
1da177e4c Linux-2.6.12-rc2 |
4 5 |
#include <linux/module.h> #include <linux/init.h> |
5a0e3ad6a include cleanup: ... |
6 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
7 8 9 10 |
#include <linux/types.h> #include <linux/string.h> #include <linux/errno.h> #include <linux/skbuff.h> |
1da177e4c Linux-2.6.12-rc2 |
11 |
#include <linux/rtnetlink.h> |
5b0ac72bc [PKT_SCHED] dsmar... |
12 |
#include <linux/bitops.h> |
1da177e4c Linux-2.6.12-rc2 |
13 14 15 16 |
#include <net/pkt_sched.h> #include <net/dsfield.h> #include <net/inet_ecn.h> #include <asm/byteorder.h> |
1da177e4c Linux-2.6.12-rc2 |
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
/* * classid class marking * ------- ----- ------- * n/a 0 n/a * x:0 1 use entry [0] * ... ... ... * x:y y>0 y+1 use entry [y] * ... ... ... * x:indices-1 indices use entry [indices-1] * ... ... ... * x:y y+1 use entry [y & (indices-1)] * ... ... ... * 0xffff 0x10000 use entry [indices-1] */ #define NO_DEFAULT_INDEX (1 << 16) struct dsmark_qdisc_data { struct Qdisc *q; struct tcf_proto *filter_list; |
af0d11417 [PKT_SCHED]: Logi... |
38 39 40 41 |
u8 *mask; /* "owns" the array */ u8 *value; u16 indices; u32 default_index; /* index range is 0...0xffff */ |
1da177e4c Linux-2.6.12-rc2 |
42 43 |
int set_tc_index; }; |
758cc43c6 [PKT_SCHED]: Fix ... |
44 45 46 47 |
static inline int dsmark_valid_index(struct dsmark_qdisc_data *p, u16 index) { return (index <= p->indices && index > 0); } |
1da177e4c Linux-2.6.12-rc2 |
48 49 |
/* ------------------------- Class/flow operations ------------------------- */ |
af0d11417 [PKT_SCHED]: Logi... |
50 51 |
static int dsmark_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, struct Qdisc **old) |
1da177e4c Linux-2.6.12-rc2 |
52 |
{ |
81da99ed7 [PKT_SCHED] dsmar... |
53 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
1da177e4c Linux-2.6.12-rc2 |
54 |
|
81da99ed7 [PKT_SCHED] dsmar... |
55 56 |
pr_debug("dsmark_graft(sch %p,[qdisc %p],new %p,old %p) ", |
af0d11417 [PKT_SCHED]: Logi... |
57 |
sch, p, new, old); |
486b53e59 [PKT_SCHED]: make... |
58 59 |
if (new == NULL) { |
3511c9132 net_sched: remove... |
60 |
new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, |
9f9afec48 [NET_SCHED]: Set ... |
61 |
sch->handle); |
486b53e59 [PKT_SCHED]: make... |
62 63 64 |
if (new == NULL) new = &noop_qdisc; } |
1da177e4c Linux-2.6.12-rc2 |
65 |
sch_tree_lock(sch); |
b94c8afcb pkt_sched: remove... |
66 67 |
*old = p->q; p->q = new; |
5e50da01d [NET_SCHED]: Fix ... |
68 |
qdisc_tree_decrease_qlen(*old, (*old)->q.qlen); |
af0d11417 [PKT_SCHED]: Logi... |
69 |
qdisc_reset(*old); |
af0d11417 [PKT_SCHED]: Logi... |
70 |
sch_tree_unlock(sch); |
10297b993 [NET] SCHED: Fix ... |
71 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
72 |
} |
1da177e4c Linux-2.6.12-rc2 |
73 74 |
static struct Qdisc *dsmark_leaf(struct Qdisc *sch, unsigned long arg) { |
81da99ed7 [PKT_SCHED] dsmar... |
75 76 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); return p->q; |
1da177e4c Linux-2.6.12-rc2 |
77 |
} |
af0d11417 [PKT_SCHED]: Logi... |
78 |
static unsigned long dsmark_get(struct Qdisc *sch, u32 classid) |
1da177e4c Linux-2.6.12-rc2 |
79 |
{ |
81da99ed7 [PKT_SCHED] dsmar... |
80 81 82 |
pr_debug("dsmark_get(sch %p,[qdisc %p],classid %x) ", sch, qdisc_priv(sch), classid); |
1da177e4c Linux-2.6.12-rc2 |
83 |
|
af0d11417 [PKT_SCHED]: Logi... |
84 |
return TC_H_MIN(classid) + 1; |
1da177e4c Linux-2.6.12-rc2 |
85 |
} |
1da177e4c Linux-2.6.12-rc2 |
86 |
static unsigned long dsmark_bind_filter(struct Qdisc *sch, |
af0d11417 [PKT_SCHED]: Logi... |
87 |
unsigned long parent, u32 classid) |
1da177e4c Linux-2.6.12-rc2 |
88 |
{ |
af0d11417 [PKT_SCHED]: Logi... |
89 |
return dsmark_get(sch, classid); |
1da177e4c Linux-2.6.12-rc2 |
90 |
} |
1da177e4c Linux-2.6.12-rc2 |
91 92 93 |
static void dsmark_put(struct Qdisc *sch, unsigned long cl) { } |
27a3421e4 [NET_SCHED]: Use ... |
94 95 96 97 98 99 100 |
static const struct nla_policy dsmark_policy[TCA_DSMARK_MAX + 1] = { [TCA_DSMARK_INDICES] = { .type = NLA_U16 }, [TCA_DSMARK_DEFAULT_INDEX] = { .type = NLA_U16 }, [TCA_DSMARK_SET_TC_INDEX] = { .type = NLA_FLAG }, [TCA_DSMARK_MASK] = { .type = NLA_U8 }, [TCA_DSMARK_VALUE] = { .type = NLA_U8 }, }; |
1da177e4c Linux-2.6.12-rc2 |
101 |
static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent, |
1e90474c3 [NET_SCHED]: Conv... |
102 |
struct nlattr **tca, unsigned long *arg) |
1da177e4c Linux-2.6.12-rc2 |
103 |
{ |
81da99ed7 [PKT_SCHED] dsmar... |
104 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
1e90474c3 [NET_SCHED]: Conv... |
105 106 |
struct nlattr *opt = tca[TCA_OPTIONS]; struct nlattr *tb[TCA_DSMARK_MAX + 1]; |
758cc43c6 [PKT_SCHED]: Fix ... |
107 108 |
int err = -EINVAL; u8 mask = 0; |
1da177e4c Linux-2.6.12-rc2 |
109 |
|
81da99ed7 [PKT_SCHED] dsmar... |
110 |
pr_debug("dsmark_change(sch %p,[qdisc %p],classid %x,parent %x)," |
758cc43c6 [PKT_SCHED]: Fix ... |
111 112 113 114 115 |
"arg 0x%lx ", sch, p, classid, parent, *arg); if (!dsmark_valid_index(p, *arg)) { err = -ENOENT; |
1e90474c3 [NET_SCHED]: Conv... |
116 |
goto errout; |
1da177e4c Linux-2.6.12-rc2 |
117 |
} |
1da177e4c Linux-2.6.12-rc2 |
118 |
|
cee63723b [NET_SCHED]: Prop... |
119 |
if (!opt) |
1e90474c3 [NET_SCHED]: Conv... |
120 |
goto errout; |
758cc43c6 [PKT_SCHED]: Fix ... |
121 |
|
27a3421e4 [NET_SCHED]: Use ... |
122 |
err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, dsmark_policy); |
cee63723b [NET_SCHED]: Prop... |
123 |
if (err < 0) |
27a3421e4 [NET_SCHED]: Use ... |
124 |
goto errout; |
cee63723b [NET_SCHED]: Prop... |
125 |
|
27a3421e4 [NET_SCHED]: Use ... |
126 |
if (tb[TCA_DSMARK_MASK]) |
1e90474c3 [NET_SCHED]: Conv... |
127 |
mask = nla_get_u8(tb[TCA_DSMARK_MASK]); |
27a3421e4 [NET_SCHED]: Use ... |
128 129 |
if (tb[TCA_DSMARK_VALUE]) |
cc7ec456f net_sched: cleanups |
130 |
p->value[*arg - 1] = nla_get_u8(tb[TCA_DSMARK_VALUE]); |
10297b993 [NET] SCHED: Fix ... |
131 |
|
1e90474c3 [NET_SCHED]: Conv... |
132 |
if (tb[TCA_DSMARK_MASK]) |
cc7ec456f net_sched: cleanups |
133 |
p->mask[*arg - 1] = mask; |
758cc43c6 [PKT_SCHED]: Fix ... |
134 135 |
err = 0; |
1e90474c3 [NET_SCHED]: Conv... |
136 |
errout: |
758cc43c6 [PKT_SCHED]: Fix ... |
137 138 |
return err; } |
1da177e4c Linux-2.6.12-rc2 |
139 |
|
af0d11417 [PKT_SCHED]: Logi... |
140 |
static int dsmark_delete(struct Qdisc *sch, unsigned long arg) |
1da177e4c Linux-2.6.12-rc2 |
141 |
{ |
81da99ed7 [PKT_SCHED] dsmar... |
142 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
1da177e4c Linux-2.6.12-rc2 |
143 |
|
af0d11417 [PKT_SCHED]: Logi... |
144 |
if (!dsmark_valid_index(p, arg)) |
1da177e4c Linux-2.6.12-rc2 |
145 |
return -EINVAL; |
10297b993 [NET] SCHED: Fix ... |
146 |
|
cc7ec456f net_sched: cleanups |
147 148 |
p->mask[arg - 1] = 0xff; p->value[arg - 1] = 0; |
af0d11417 [PKT_SCHED]: Logi... |
149 |
|
1da177e4c Linux-2.6.12-rc2 |
150 151 |
return 0; } |
9d127fbdd [PKT_SCHED] dsmar... |
152 |
static void dsmark_walk(struct Qdisc *sch, struct qdisc_walker *walker) |
1da177e4c Linux-2.6.12-rc2 |
153 |
{ |
81da99ed7 [PKT_SCHED] dsmar... |
154 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
1da177e4c Linux-2.6.12-rc2 |
155 |
int i; |
81da99ed7 [PKT_SCHED] dsmar... |
156 157 |
pr_debug("dsmark_walk(sch %p,[qdisc %p],walker %p) ", sch, p, walker); |
af0d11417 [PKT_SCHED]: Logi... |
158 |
|
1da177e4c Linux-2.6.12-rc2 |
159 160 |
if (walker->stop) return; |
af0d11417 [PKT_SCHED]: Logi... |
161 |
|
1da177e4c Linux-2.6.12-rc2 |
162 163 |
for (i = 0; i < p->indices; i++) { if (p->mask[i] == 0xff && !p->value[i]) |
0451eb074 [PKT_SCHED]: Fix ... |
164 |
goto ignore; |
1da177e4c Linux-2.6.12-rc2 |
165 |
if (walker->count >= walker->skip) { |
cc7ec456f net_sched: cleanups |
166 |
if (walker->fn(sch, i + 1, walker) < 0) { |
1da177e4c Linux-2.6.12-rc2 |
167 168 169 170 |
walker->stop = 1; break; } } |
10297b993 [NET] SCHED: Fix ... |
171 |
ignore: |
0451eb074 [PKT_SCHED]: Fix ... |
172 |
walker->count++; |
10297b993 [NET] SCHED: Fix ... |
173 |
} |
1da177e4c Linux-2.6.12-rc2 |
174 |
} |
9d127fbdd [PKT_SCHED] dsmar... |
175 176 |
static inline struct tcf_proto **dsmark_find_tcf(struct Qdisc *sch, unsigned long cl) |
1da177e4c Linux-2.6.12-rc2 |
177 |
{ |
81da99ed7 [PKT_SCHED] dsmar... |
178 179 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); return &p->filter_list; |
1da177e4c Linux-2.6.12-rc2 |
180 |
} |
1da177e4c Linux-2.6.12-rc2 |
181 |
/* --------------------------- Qdisc operations ---------------------------- */ |
9d127fbdd [PKT_SCHED] dsmar... |
182 |
static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch) |
1da177e4c Linux-2.6.12-rc2 |
183 |
{ |
81da99ed7 [PKT_SCHED] dsmar... |
184 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
af0d11417 [PKT_SCHED]: Logi... |
185 |
int err; |
81da99ed7 [PKT_SCHED] dsmar... |
186 187 |
pr_debug("dsmark_enqueue(skb %p,sch %p,[qdisc %p]) ", skb, sch, p); |
1da177e4c Linux-2.6.12-rc2 |
188 |
|
1da177e4c Linux-2.6.12-rc2 |
189 |
if (p->set_tc_index) { |
1da177e4c Linux-2.6.12-rc2 |
190 |
switch (skb->protocol) { |
606780404 net: Use hton[sl]... |
191 |
case htons(ETH_P_IP): |
9d127fbdd [PKT_SCHED] dsmar... |
192 193 |
if (skb_cow_head(skb, sizeof(struct iphdr))) goto drop; |
4c30719f4 [PKT_SCHED] dsmar... |
194 |
|
9d127fbdd [PKT_SCHED] dsmar... |
195 196 197 |
skb->tc_index = ipv4_get_dsfield(ip_hdr(skb)) & ~INET_ECN_MASK; break; |
4c30719f4 [PKT_SCHED] dsmar... |
198 |
|
606780404 net: Use hton[sl]... |
199 |
case htons(ETH_P_IPV6): |
9d127fbdd [PKT_SCHED] dsmar... |
200 201 |
if (skb_cow_head(skb, sizeof(struct ipv6hdr))) goto drop; |
4c30719f4 [PKT_SCHED] dsmar... |
202 |
|
9d127fbdd [PKT_SCHED] dsmar... |
203 204 205 206 207 208 |
skb->tc_index = ipv6_get_dsfield(ipv6_hdr(skb)) & ~INET_ECN_MASK; break; default: skb->tc_index = 0; break; |
3ff50b799 [NET]: cleanup ex... |
209 |
} |
1da177e4c Linux-2.6.12-rc2 |
210 |
} |
af0d11417 [PKT_SCHED]: Logi... |
211 212 |
if (TC_H_MAJ(skb->priority) == sch->handle) |
1da177e4c Linux-2.6.12-rc2 |
213 |
skb->tc_index = TC_H_MIN(skb->priority); |
af0d11417 [PKT_SCHED]: Logi... |
214 215 216 |
else { struct tcf_result res; int result = tc_classify(skb, p->filter_list, &res); |
81da99ed7 [PKT_SCHED] dsmar... |
217 218 |
pr_debug("result %d class 0x%04x ", result, res.classid); |
af0d11417 [PKT_SCHED]: Logi... |
219 |
|
1da177e4c Linux-2.6.12-rc2 |
220 |
switch (result) { |
f6853e2df [NET_SCHED]: sch_... |
221 222 223 224 |
#ifdef CONFIG_NET_CLS_ACT case TC_ACT_QUEUED: case TC_ACT_STOLEN: kfree_skb(skb); |
378a2f090 net_sched: Add qd... |
225 |
return NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; |
4c30719f4 [PKT_SCHED] dsmar... |
226 |
|
f6853e2df [NET_SCHED]: sch_... |
227 |
case TC_ACT_SHOT: |
4c30719f4 [PKT_SCHED] dsmar... |
228 |
goto drop; |
1da177e4c Linux-2.6.12-rc2 |
229 |
#endif |
c3bc7cff8 [NET_SCHED]: Kill... |
230 |
case TC_ACT_OK: |
f6853e2df [NET_SCHED]: sch_... |
231 232 |
skb->tc_index = TC_H_MIN(res.classid); break; |
4c30719f4 [PKT_SCHED] dsmar... |
233 |
|
f6853e2df [NET_SCHED]: sch_... |
234 235 236 237 |
default: if (p->default_index != NO_DEFAULT_INDEX) skb->tc_index = p->default_index; break; |
3ff50b799 [NET]: cleanup ex... |
238 |
} |
1da177e4c Linux-2.6.12-rc2 |
239 |
} |
1da177e4c Linux-2.6.12-rc2 |
240 |
|
5f86173bd net_sched: Add qd... |
241 |
err = qdisc_enqueue(skb, p->q); |
af0d11417 [PKT_SCHED]: Logi... |
242 |
if (err != NET_XMIT_SUCCESS) { |
378a2f090 net_sched: Add qd... |
243 244 |
if (net_xmit_drop_count(err)) sch->qstats.drops++; |
af0d11417 [PKT_SCHED]: Logi... |
245 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
246 |
} |
af0d11417 [PKT_SCHED]: Logi... |
247 |
|
1da177e4c Linux-2.6.12-rc2 |
248 |
sch->q.qlen++; |
1da177e4c Linux-2.6.12-rc2 |
249 |
|
af0d11417 [PKT_SCHED]: Logi... |
250 |
return NET_XMIT_SUCCESS; |
4c30719f4 [PKT_SCHED] dsmar... |
251 252 253 254 |
drop: kfree_skb(skb); sch->qstats.drops++; |
c27f339af net_sched: Add qd... |
255 |
return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; |
af0d11417 [PKT_SCHED]: Logi... |
256 |
} |
1da177e4c Linux-2.6.12-rc2 |
257 258 259 |
static struct sk_buff *dsmark_dequeue(struct Qdisc *sch) { |
81da99ed7 [PKT_SCHED] dsmar... |
260 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
1da177e4c Linux-2.6.12-rc2 |
261 |
struct sk_buff *skb; |
af0d11417 [PKT_SCHED]: Logi... |
262 |
u32 index; |
81da99ed7 [PKT_SCHED] dsmar... |
263 264 |
pr_debug("dsmark_dequeue(sch %p,[qdisc %p]) ", sch, p); |
1da177e4c Linux-2.6.12-rc2 |
265 |
|
1da177e4c Linux-2.6.12-rc2 |
266 |
skb = p->q->ops->dequeue(p->q); |
af0d11417 [PKT_SCHED]: Logi... |
267 |
if (skb == NULL) |
1da177e4c Linux-2.6.12-rc2 |
268 |
return NULL; |
af0d11417 [PKT_SCHED]: Logi... |
269 |
|
9190b3b32 net_sched: accura... |
270 |
qdisc_bstats_update(sch, skb); |
1da177e4c Linux-2.6.12-rc2 |
271 |
sch->q.qlen--; |
af0d11417 [PKT_SCHED]: Logi... |
272 273 |
index = skb->tc_index & (p->indices - 1); |
81da99ed7 [PKT_SCHED] dsmar... |
274 275 |
pr_debug("index %d->%d ", skb->tc_index, index); |
af0d11417 [PKT_SCHED]: Logi... |
276 |
|
1da177e4c Linux-2.6.12-rc2 |
277 |
switch (skb->protocol) { |
606780404 net: Use hton[sl]... |
278 |
case htons(ETH_P_IP): |
9d127fbdd [PKT_SCHED] dsmar... |
279 280 |
ipv4_change_dsfield(ip_hdr(skb), p->mask[index], p->value[index]); |
1da177e4c Linux-2.6.12-rc2 |
281 |
break; |
606780404 net: Use hton[sl]... |
282 |
case htons(ETH_P_IPV6): |
9d127fbdd [PKT_SCHED] dsmar... |
283 284 |
ipv6_change_dsfield(ipv6_hdr(skb), p->mask[index], p->value[index]); |
1da177e4c Linux-2.6.12-rc2 |
285 |
break; |
9d127fbdd [PKT_SCHED] dsmar... |
286 287 288 289 290 291 292 |
default: /* * Only complain if a change was actually attempted. * This way, we can send non-IP traffic through dsmark * and don't need yet another qdisc as a bypass. */ if (p->mask[index] != 0xff || p->value[index]) |
cc7ec456f net_sched: cleanups |
293 294 295 |
pr_warning("dsmark_dequeue: unsupported protocol %d ", ntohs(skb->protocol)); |
9d127fbdd [PKT_SCHED] dsmar... |
296 |
break; |
3ff50b799 [NET]: cleanup ex... |
297 |
} |
af0d11417 [PKT_SCHED]: Logi... |
298 |
|
1da177e4c Linux-2.6.12-rc2 |
299 300 |
return skb; } |
8e3af9789 pkt_sched: Add qd... |
301 302 303 304 305 306 307 308 309 |
static struct sk_buff *dsmark_peek(struct Qdisc *sch) { struct dsmark_qdisc_data *p = qdisc_priv(sch); pr_debug("dsmark_peek(sch %p,[qdisc %p]) ", sch, p); return p->q->ops->peek(p->q); } |
1da177e4c Linux-2.6.12-rc2 |
310 311 |
static unsigned int dsmark_drop(struct Qdisc *sch) { |
81da99ed7 [PKT_SCHED] dsmar... |
312 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
1da177e4c Linux-2.6.12-rc2 |
313 |
unsigned int len; |
10297b993 [NET] SCHED: Fix ... |
314 |
|
81da99ed7 [PKT_SCHED] dsmar... |
315 316 |
pr_debug("dsmark_reset(sch %p,[qdisc %p]) ", sch, p); |
af0d11417 [PKT_SCHED]: Logi... |
317 318 |
if (p->q->ops->drop == NULL) |
1da177e4c Linux-2.6.12-rc2 |
319 |
return 0; |
af0d11417 [PKT_SCHED]: Logi... |
320 321 322 323 |
len = p->q->ops->drop(p->q); if (len) sch->q.qlen--; |
1da177e4c Linux-2.6.12-rc2 |
324 325 |
return len; } |
1e90474c3 [NET_SCHED]: Conv... |
326 |
static int dsmark_init(struct Qdisc *sch, struct nlattr *opt) |
1da177e4c Linux-2.6.12-rc2 |
327 |
{ |
81da99ed7 [PKT_SCHED] dsmar... |
328 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
1e90474c3 [NET_SCHED]: Conv... |
329 |
struct nlattr *tb[TCA_DSMARK_MAX + 1]; |
758cc43c6 [PKT_SCHED]: Fix ... |
330 331 332 333 |
int err = -EINVAL; u32 default_index = NO_DEFAULT_INDEX; u16 indices; u8 *mask; |
81da99ed7 [PKT_SCHED] dsmar... |
334 335 |
pr_debug("dsmark_init(sch %p,[qdisc %p],opt %p) ", sch, p, opt); |
758cc43c6 [PKT_SCHED]: Fix ... |
336 |
|
cee63723b [NET_SCHED]: Prop... |
337 338 |
if (!opt) goto errout; |
27a3421e4 [NET_SCHED]: Use ... |
339 |
err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, dsmark_policy); |
cee63723b [NET_SCHED]: Prop... |
340 |
if (err < 0) |
758cc43c6 [PKT_SCHED]: Fix ... |
341 |
goto errout; |
cee63723b [NET_SCHED]: Prop... |
342 |
err = -EINVAL; |
1e90474c3 [NET_SCHED]: Conv... |
343 |
indices = nla_get_u16(tb[TCA_DSMARK_INDICES]); |
5b0ac72bc [PKT_SCHED] dsmar... |
344 345 |
if (hweight32(indices) != 1) |
758cc43c6 [PKT_SCHED]: Fix ... |
346 |
goto errout; |
27a3421e4 [NET_SCHED]: Use ... |
347 |
if (tb[TCA_DSMARK_DEFAULT_INDEX]) |
1e90474c3 [NET_SCHED]: Conv... |
348 |
default_index = nla_get_u16(tb[TCA_DSMARK_DEFAULT_INDEX]); |
758cc43c6 [PKT_SCHED]: Fix ... |
349 350 351 352 353 |
mask = kmalloc(indices * 2, GFP_KERNEL); if (mask == NULL) { err = -ENOMEM; goto errout; |
1da177e4c Linux-2.6.12-rc2 |
354 |
} |
758cc43c6 [PKT_SCHED]: Fix ... |
355 356 357 358 359 360 361 362 363 |
p->mask = mask; memset(p->mask, 0xff, indices); p->value = p->mask + indices; memset(p->value, 0, indices); p->indices = indices; p->default_index = default_index; |
1e90474c3 [NET_SCHED]: Conv... |
364 |
p->set_tc_index = nla_get_flag(tb[TCA_DSMARK_SET_TC_INDEX]); |
758cc43c6 [PKT_SCHED]: Fix ... |
365 |
|
3511c9132 net_sched: remove... |
366 |
p->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, sch->handle); |
758cc43c6 [PKT_SCHED]: Fix ... |
367 |
if (p->q == NULL) |
1da177e4c Linux-2.6.12-rc2 |
368 |
p->q = &noop_qdisc; |
758cc43c6 [PKT_SCHED]: Fix ... |
369 |
|
81da99ed7 [PKT_SCHED] dsmar... |
370 371 |
pr_debug("dsmark_init: qdisc %p ", p->q); |
758cc43c6 [PKT_SCHED]: Fix ... |
372 373 374 |
err = 0; errout: |
758cc43c6 [PKT_SCHED]: Fix ... |
375 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
376 |
} |
1da177e4c Linux-2.6.12-rc2 |
377 378 |
static void dsmark_reset(struct Qdisc *sch) { |
81da99ed7 [PKT_SCHED] dsmar... |
379 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
1da177e4c Linux-2.6.12-rc2 |
380 |
|
81da99ed7 [PKT_SCHED] dsmar... |
381 382 |
pr_debug("dsmark_reset(sch %p,[qdisc %p]) ", sch, p); |
1da177e4c Linux-2.6.12-rc2 |
383 384 385 |
qdisc_reset(p->q); sch->q.qlen = 0; } |
1da177e4c Linux-2.6.12-rc2 |
386 387 |
static void dsmark_destroy(struct Qdisc *sch) { |
81da99ed7 [PKT_SCHED] dsmar... |
388 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
1da177e4c Linux-2.6.12-rc2 |
389 |
|
81da99ed7 [PKT_SCHED] dsmar... |
390 391 |
pr_debug("dsmark_destroy(sch %p,[qdisc %p]) ", sch, p); |
af0d11417 [PKT_SCHED]: Logi... |
392 |
|
ff31ab56c net-sched: change... |
393 |
tcf_destroy_chain(&p->filter_list); |
1da177e4c Linux-2.6.12-rc2 |
394 395 396 |
qdisc_destroy(p->q); kfree(p->mask); } |
1da177e4c Linux-2.6.12-rc2 |
397 |
static int dsmark_dump_class(struct Qdisc *sch, unsigned long cl, |
02f23f095 [PKT_SCHED]: Make... |
398 |
struct sk_buff *skb, struct tcmsg *tcm) |
1da177e4c Linux-2.6.12-rc2 |
399 |
{ |
81da99ed7 [PKT_SCHED] dsmar... |
400 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
1e90474c3 [NET_SCHED]: Conv... |
401 |
struct nlattr *opts = NULL; |
1da177e4c Linux-2.6.12-rc2 |
402 |
|
81da99ed7 [PKT_SCHED] dsmar... |
403 404 |
pr_debug("dsmark_dump_class(sch %p,[qdisc %p],class %ld ", sch, p, cl); |
02f23f095 [PKT_SCHED]: Make... |
405 406 |
if (!dsmark_valid_index(p, cl)) |
1da177e4c Linux-2.6.12-rc2 |
407 |
return -EINVAL; |
02f23f095 [PKT_SCHED]: Make... |
408 |
|
cc7ec456f net_sched: cleanups |
409 |
tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle), cl - 1); |
cdc7f8e36 [PKT_SCHED]: Dump... |
410 |
tcm->tcm_info = p->q->handle; |
02f23f095 [PKT_SCHED]: Make... |
411 |
|
1e90474c3 [NET_SCHED]: Conv... |
412 413 414 |
opts = nla_nest_start(skb, TCA_OPTIONS); if (opts == NULL) goto nla_put_failure; |
cc7ec456f net_sched: cleanups |
415 416 |
NLA_PUT_U8(skb, TCA_DSMARK_MASK, p->mask[cl - 1]); NLA_PUT_U8(skb, TCA_DSMARK_VALUE, p->value[cl - 1]); |
02f23f095 [PKT_SCHED]: Make... |
417 |
|
1e90474c3 [NET_SCHED]: Conv... |
418 |
return nla_nest_end(skb, opts); |
1da177e4c Linux-2.6.12-rc2 |
419 |
|
1e90474c3 [NET_SCHED]: Conv... |
420 |
nla_put_failure: |
bc3ed28ca netlink: Improve ... |
421 422 |
nla_nest_cancel(skb, opts); return -EMSGSIZE; |
1da177e4c Linux-2.6.12-rc2 |
423 424 425 426 |
} static int dsmark_dump(struct Qdisc *sch, struct sk_buff *skb) { |
81da99ed7 [PKT_SCHED] dsmar... |
427 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
1e90474c3 [NET_SCHED]: Conv... |
428 |
struct nlattr *opts = NULL; |
1da177e4c Linux-2.6.12-rc2 |
429 |
|
1e90474c3 [NET_SCHED]: Conv... |
430 431 432 433 |
opts = nla_nest_start(skb, TCA_OPTIONS); if (opts == NULL) goto nla_put_failure; NLA_PUT_U16(skb, TCA_DSMARK_INDICES, p->indices); |
02f23f095 [PKT_SCHED]: Make... |
434 435 |
if (p->default_index != NO_DEFAULT_INDEX) |
1e90474c3 [NET_SCHED]: Conv... |
436 |
NLA_PUT_U16(skb, TCA_DSMARK_DEFAULT_INDEX, p->default_index); |
1da177e4c Linux-2.6.12-rc2 |
437 |
|
1da177e4c Linux-2.6.12-rc2 |
438 |
if (p->set_tc_index) |
1e90474c3 [NET_SCHED]: Conv... |
439 |
NLA_PUT_FLAG(skb, TCA_DSMARK_SET_TC_INDEX); |
02f23f095 [PKT_SCHED]: Make... |
440 |
|
1e90474c3 [NET_SCHED]: Conv... |
441 |
return nla_nest_end(skb, opts); |
1da177e4c Linux-2.6.12-rc2 |
442 |
|
1e90474c3 [NET_SCHED]: Conv... |
443 |
nla_put_failure: |
bc3ed28ca netlink: Improve ... |
444 445 |
nla_nest_cancel(skb, opts); return -EMSGSIZE; |
1da177e4c Linux-2.6.12-rc2 |
446 |
} |
20fea08b5 [NET]: Move Qdisc... |
447 |
static const struct Qdisc_class_ops dsmark_class_ops = { |
1da177e4c Linux-2.6.12-rc2 |
448 449 450 451 452 453 454 455 456 457 458 459 |
.graft = dsmark_graft, .leaf = dsmark_leaf, .get = dsmark_get, .put = dsmark_put, .change = dsmark_change, .delete = dsmark_delete, .walk = dsmark_walk, .tcf_chain = dsmark_find_tcf, .bind_tcf = dsmark_bind_filter, .unbind_tcf = dsmark_put, .dump = dsmark_dump_class, }; |
20fea08b5 [NET]: Move Qdisc... |
460 |
static struct Qdisc_ops dsmark_qdisc_ops __read_mostly = { |
1da177e4c Linux-2.6.12-rc2 |
461 462 463 464 465 466 |
.next = NULL, .cl_ops = &dsmark_class_ops, .id = "dsmark", .priv_size = sizeof(struct dsmark_qdisc_data), .enqueue = dsmark_enqueue, .dequeue = dsmark_dequeue, |
8e3af9789 pkt_sched: Add qd... |
467 |
.peek = dsmark_peek, |
1da177e4c Linux-2.6.12-rc2 |
468 469 470 471 472 473 474 475 476 477 478 479 480 |
.drop = dsmark_drop, .init = dsmark_init, .reset = dsmark_reset, .destroy = dsmark_destroy, .change = NULL, .dump = dsmark_dump, .owner = THIS_MODULE, }; static int __init dsmark_module_init(void) { return register_qdisc(&dsmark_qdisc_ops); } |
af0d11417 [PKT_SCHED]: Logi... |
481 |
|
10297b993 [NET] SCHED: Fix ... |
482 |
static void __exit dsmark_module_exit(void) |
1da177e4c Linux-2.6.12-rc2 |
483 484 485 |
{ unregister_qdisc(&dsmark_qdisc_ops); } |
af0d11417 [PKT_SCHED]: Logi... |
486 |
|
1da177e4c Linux-2.6.12-rc2 |
487 488 |
module_init(dsmark_module_init) module_exit(dsmark_module_exit) |
af0d11417 [PKT_SCHED]: Logi... |
489 |
|
1da177e4c Linux-2.6.12-rc2 |
490 |
MODULE_LICENSE("GPL"); |