Blame view
net/sched/sch_dsmark.c
11.9 KB
09c434b8a treewide: Add SPD... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 |
/* net/sched/sch_dsmark.c - Differentiated Services field marker */ /* Written 1998-2000 by Werner Almesberger, EPFL ICA */ |
1da177e4c Linux-2.6.12-rc2 |
5 6 |
#include <linux/module.h> #include <linux/init.h> |
5a0e3ad6a include cleanup: ... |
7 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
8 9 10 11 |
#include <linux/types.h> #include <linux/string.h> #include <linux/errno.h> #include <linux/skbuff.h> |
1da177e4c Linux-2.6.12-rc2 |
12 |
#include <linux/rtnetlink.h> |
5b0ac72bc [PKT_SCHED] dsmar... |
13 |
#include <linux/bitops.h> |
1da177e4c Linux-2.6.12-rc2 |
14 |
#include <net/pkt_sched.h> |
cf1facda2 sched: move tcf_p... |
15 |
#include <net/pkt_cls.h> |
1da177e4c Linux-2.6.12-rc2 |
16 17 18 |
#include <net/dsfield.h> #include <net/inet_ecn.h> #include <asm/byteorder.h> |
1da177e4c Linux-2.6.12-rc2 |
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
/* * 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) |
47bbbb30b sch_dsmark: impro... |
36 37 38 39 |
struct mask_value { u8 mask; u8 value; }; |
1da177e4c Linux-2.6.12-rc2 |
40 41 |
struct dsmark_qdisc_data { struct Qdisc *q; |
25d8c0d55 net: rcu-ify tcf_... |
42 |
struct tcf_proto __rcu *filter_list; |
6529eaba3 net: sched: intro... |
43 |
struct tcf_block *block; |
47bbbb30b sch_dsmark: impro... |
44 |
struct mask_value *mv; |
af0d11417 [PKT_SCHED]: Logi... |
45 |
u16 indices; |
47bbbb30b sch_dsmark: impro... |
46 |
u8 set_tc_index; |
af0d11417 [PKT_SCHED]: Logi... |
47 |
u32 default_index; /* index range is 0...0xffff */ |
47bbbb30b sch_dsmark: impro... |
48 49 |
#define DSMARK_EMBEDDED_SZ 16 struct mask_value embedded[DSMARK_EMBEDDED_SZ]; |
1da177e4c Linux-2.6.12-rc2 |
50 |
}; |
758cc43c6 [PKT_SCHED]: Fix ... |
51 52 |
static inline int dsmark_valid_index(struct dsmark_qdisc_data *p, u16 index) { |
17569faed net_sched: remove... |
53 |
return index <= p->indices && index > 0; |
758cc43c6 [PKT_SCHED]: Fix ... |
54 |
} |
1da177e4c Linux-2.6.12-rc2 |
55 56 |
/* ------------------------- Class/flow operations ------------------------- */ |
af0d11417 [PKT_SCHED]: Logi... |
57 |
static int dsmark_graft(struct Qdisc *sch, unsigned long arg, |
653d6fd68 net: sched: sch: ... |
58 59 |
struct Qdisc *new, struct Qdisc **old, struct netlink_ext_ack *extack) |
1da177e4c Linux-2.6.12-rc2 |
60 |
{ |
81da99ed7 [PKT_SCHED] dsmar... |
61 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
1da177e4c Linux-2.6.12-rc2 |
62 |
|
c76f2a2c4 sch_dsmark: use c... |
63 64 65 |
pr_debug("%s(sch %p,[qdisc %p],new %p,old %p) ", __func__, sch, p, new, old); |
486b53e59 [PKT_SCHED]: make... |
66 67 |
if (new == NULL) { |
3511c9132 net_sched: remove... |
68 |
new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, |
a38a98821 net: sch: api: ad... |
69 |
sch->handle, NULL); |
486b53e59 [PKT_SCHED]: make... |
70 71 72 |
if (new == NULL) new = &noop_qdisc; } |
86a7996cc net_sched: introd... |
73 |
*old = qdisc_replace(sch, new, &p->q); |
10297b993 [NET] SCHED: Fix ... |
74 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
75 |
} |
1da177e4c Linux-2.6.12-rc2 |
76 77 |
static struct Qdisc *dsmark_leaf(struct Qdisc *sch, unsigned long arg) { |
81da99ed7 [PKT_SCHED] dsmar... |
78 79 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); return p->q; |
1da177e4c Linux-2.6.12-rc2 |
80 |
} |
143976ce9 net_sched: remove... |
81 |
static unsigned long dsmark_find(struct Qdisc *sch, u32 classid) |
1da177e4c Linux-2.6.12-rc2 |
82 |
{ |
af0d11417 [PKT_SCHED]: Logi... |
83 |
return TC_H_MIN(classid) + 1; |
1da177e4c Linux-2.6.12-rc2 |
84 |
} |
1da177e4c Linux-2.6.12-rc2 |
85 |
static unsigned long dsmark_bind_filter(struct Qdisc *sch, |
af0d11417 [PKT_SCHED]: Logi... |
86 |
unsigned long parent, u32 classid) |
1da177e4c Linux-2.6.12-rc2 |
87 |
{ |
143976ce9 net_sched: remove... |
88 89 90 91 92 |
pr_debug("%s(sch %p,[qdisc %p],classid %x) ", __func__, sch, qdisc_priv(sch), classid); return dsmark_find(sch, classid); |
1da177e4c Linux-2.6.12-rc2 |
93 |
} |
143976ce9 net_sched: remove... |
94 |
static void dsmark_unbind_filter(struct Qdisc *sch, unsigned long cl) |
1da177e4c Linux-2.6.12-rc2 |
95 96 |
{ } |
27a3421e4 [NET_SCHED]: Use ... |
97 98 99 100 101 102 103 |
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 |
104 |
static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent, |
793d81d6a net: sched: sch: ... |
105 106 |
struct nlattr **tca, unsigned long *arg, struct netlink_ext_ack *extack) |
1da177e4c Linux-2.6.12-rc2 |
107 |
{ |
81da99ed7 [PKT_SCHED] dsmar... |
108 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
1e90474c3 [NET_SCHED]: Conv... |
109 110 |
struct nlattr *opt = tca[TCA_OPTIONS]; struct nlattr *tb[TCA_DSMARK_MAX + 1]; |
758cc43c6 [PKT_SCHED]: Fix ... |
111 |
int err = -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
112 |
|
c76f2a2c4 sch_dsmark: use c... |
113 114 115 |
pr_debug("%s(sch %p,[qdisc %p],classid %x,parent %x), arg 0x%lx ", __func__, sch, p, classid, parent, *arg); |
758cc43c6 [PKT_SCHED]: Fix ... |
116 117 118 |
if (!dsmark_valid_index(p, *arg)) { err = -ENOENT; |
1e90474c3 [NET_SCHED]: Conv... |
119 |
goto errout; |
1da177e4c Linux-2.6.12-rc2 |
120 |
} |
1da177e4c Linux-2.6.12-rc2 |
121 |
|
cee63723b [NET_SCHED]: Prop... |
122 |
if (!opt) |
1e90474c3 [NET_SCHED]: Conv... |
123 |
goto errout; |
758cc43c6 [PKT_SCHED]: Fix ... |
124 |
|
8cb081746 netlink: make val... |
125 126 |
err = nla_parse_nested_deprecated(tb, TCA_DSMARK_MAX, opt, dsmark_policy, NULL); |
cee63723b [NET_SCHED]: Prop... |
127 |
if (err < 0) |
27a3421e4 [NET_SCHED]: Use ... |
128 |
goto errout; |
cee63723b [NET_SCHED]: Prop... |
129 |
|
27a3421e4 [NET_SCHED]: Use ... |
130 |
if (tb[TCA_DSMARK_VALUE]) |
47bbbb30b sch_dsmark: impro... |
131 |
p->mv[*arg - 1].value = nla_get_u8(tb[TCA_DSMARK_VALUE]); |
10297b993 [NET] SCHED: Fix ... |
132 |
|
1e90474c3 [NET_SCHED]: Conv... |
133 |
if (tb[TCA_DSMARK_MASK]) |
47bbbb30b sch_dsmark: impro... |
134 |
p->mv[*arg - 1].mask = nla_get_u8(tb[TCA_DSMARK_MASK]); |
758cc43c6 [PKT_SCHED]: Fix ... |
135 136 |
err = 0; |
1e90474c3 [NET_SCHED]: Conv... |
137 |
errout: |
758cc43c6 [PKT_SCHED]: Fix ... |
138 139 |
return err; } |
1da177e4c Linux-2.6.12-rc2 |
140 |
|
af0d11417 [PKT_SCHED]: Logi... |
141 |
static int dsmark_delete(struct Qdisc *sch, unsigned long arg) |
1da177e4c Linux-2.6.12-rc2 |
142 |
{ |
81da99ed7 [PKT_SCHED] dsmar... |
143 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
1da177e4c Linux-2.6.12-rc2 |
144 |
|
af0d11417 [PKT_SCHED]: Logi... |
145 |
if (!dsmark_valid_index(p, arg)) |
1da177e4c Linux-2.6.12-rc2 |
146 |
return -EINVAL; |
10297b993 [NET] SCHED: Fix ... |
147 |
|
47bbbb30b sch_dsmark: impro... |
148 149 |
p->mv[arg - 1].mask = 0xff; p->mv[arg - 1].value = 0; |
af0d11417 [PKT_SCHED]: Logi... |
150 |
|
1da177e4c Linux-2.6.12-rc2 |
151 152 |
return 0; } |
9d127fbdd [PKT_SCHED] dsmar... |
153 |
static void dsmark_walk(struct Qdisc *sch, struct qdisc_walker *walker) |
1da177e4c Linux-2.6.12-rc2 |
154 |
{ |
81da99ed7 [PKT_SCHED] dsmar... |
155 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
1da177e4c Linux-2.6.12-rc2 |
156 |
int i; |
c76f2a2c4 sch_dsmark: use c... |
157 158 159 |
pr_debug("%s(sch %p,[qdisc %p],walker %p) ", __func__, sch, p, walker); |
af0d11417 [PKT_SCHED]: Logi... |
160 |
|
1da177e4c Linux-2.6.12-rc2 |
161 162 |
if (walker->stop) return; |
af0d11417 [PKT_SCHED]: Logi... |
163 |
|
1da177e4c Linux-2.6.12-rc2 |
164 |
for (i = 0; i < p->indices; i++) { |
47bbbb30b sch_dsmark: impro... |
165 |
if (p->mv[i].mask == 0xff && !p->mv[i].value) |
0451eb074 [PKT_SCHED]: Fix ... |
166 |
goto ignore; |
1da177e4c Linux-2.6.12-rc2 |
167 |
if (walker->count >= walker->skip) { |
cc7ec456f net_sched: cleanups |
168 |
if (walker->fn(sch, i + 1, walker) < 0) { |
1da177e4c Linux-2.6.12-rc2 |
169 170 171 172 |
walker->stop = 1; break; } } |
10297b993 [NET] SCHED: Fix ... |
173 |
ignore: |
0451eb074 [PKT_SCHED]: Fix ... |
174 |
walker->count++; |
10297b993 [NET] SCHED: Fix ... |
175 |
} |
1da177e4c Linux-2.6.12-rc2 |
176 |
} |
cbaacc4e8 net: sched: sch: ... |
177 178 |
static struct tcf_block *dsmark_tcf_block(struct Qdisc *sch, unsigned long cl, struct netlink_ext_ack *extack) |
1da177e4c Linux-2.6.12-rc2 |
179 |
{ |
81da99ed7 [PKT_SCHED] dsmar... |
180 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
6529eaba3 net: sched: intro... |
181 182 |
return p->block; |
1da177e4c Linux-2.6.12-rc2 |
183 |
} |
1da177e4c Linux-2.6.12-rc2 |
184 |
/* --------------------------- Qdisc operations ---------------------------- */ |
520ac30f4 net_sched: drop p... |
185 186 |
static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) |
1da177e4c Linux-2.6.12-rc2 |
187 |
{ |
f6bab1993 sched: Avoid dere... |
188 |
unsigned int len = qdisc_pkt_len(skb); |
81da99ed7 [PKT_SCHED] dsmar... |
189 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
af0d11417 [PKT_SCHED]: Logi... |
190 |
int err; |
c76f2a2c4 sch_dsmark: use c... |
191 192 |
pr_debug("%s(skb %p,sch %p,[qdisc %p]) ", __func__, skb, sch, p); |
1da177e4c Linux-2.6.12-rc2 |
193 |
|
1da177e4c Linux-2.6.12-rc2 |
194 |
if (p->set_tc_index) { |
aea92fb2e sch_dsmark: fix i... |
195 |
int wlen = skb_network_offset(skb); |
d7bf2ebeb sched: consistent... |
196 |
switch (skb_protocol(skb, true)) { |
606780404 net: Use hton[sl]... |
197 |
case htons(ETH_P_IP): |
aea92fb2e sch_dsmark: fix i... |
198 199 200 |
wlen += sizeof(struct iphdr); if (!pskb_may_pull(skb, wlen) || skb_try_make_writable(skb, wlen)) |
9d127fbdd [PKT_SCHED] dsmar... |
201 |
goto drop; |
4c30719f4 [PKT_SCHED] dsmar... |
202 |
|
9d127fbdd [PKT_SCHED] dsmar... |
203 204 205 |
skb->tc_index = ipv4_get_dsfield(ip_hdr(skb)) & ~INET_ECN_MASK; break; |
4c30719f4 [PKT_SCHED] dsmar... |
206 |
|
606780404 net: Use hton[sl]... |
207 |
case htons(ETH_P_IPV6): |
aea92fb2e sch_dsmark: fix i... |
208 209 210 |
wlen += sizeof(struct ipv6hdr); if (!pskb_may_pull(skb, wlen) || skb_try_make_writable(skb, wlen)) |
9d127fbdd [PKT_SCHED] dsmar... |
211 |
goto drop; |
4c30719f4 [PKT_SCHED] dsmar... |
212 |
|
9d127fbdd [PKT_SCHED] dsmar... |
213 214 215 216 217 218 |
skb->tc_index = ipv6_get_dsfield(ipv6_hdr(skb)) & ~INET_ECN_MASK; break; default: skb->tc_index = 0; break; |
3ff50b799 [NET]: cleanup ex... |
219 |
} |
1da177e4c Linux-2.6.12-rc2 |
220 |
} |
af0d11417 [PKT_SCHED]: Logi... |
221 222 |
if (TC_H_MAJ(skb->priority) == sch->handle) |
1da177e4c Linux-2.6.12-rc2 |
223 |
skb->tc_index = TC_H_MIN(skb->priority); |
af0d11417 [PKT_SCHED]: Logi... |
224 225 |
else { struct tcf_result res; |
25d8c0d55 net: rcu-ify tcf_... |
226 |
struct tcf_proto *fl = rcu_dereference_bh(p->filter_list); |
87d83093b net: sched: move ... |
227 |
int result = tcf_classify(skb, fl, &res, false); |
af0d11417 [PKT_SCHED]: Logi... |
228 |
|
81da99ed7 [PKT_SCHED] dsmar... |
229 230 |
pr_debug("result %d class 0x%04x ", result, res.classid); |
af0d11417 [PKT_SCHED]: Logi... |
231 |
|
1da177e4c Linux-2.6.12-rc2 |
232 |
switch (result) { |
f6853e2df [NET_SCHED]: sch_... |
233 234 235 |
#ifdef CONFIG_NET_CLS_ACT case TC_ACT_QUEUED: case TC_ACT_STOLEN: |
e25ea21ff net: sched: intro... |
236 |
case TC_ACT_TRAP: |
520ac30f4 net_sched: drop p... |
237 |
__qdisc_drop(skb, to_free); |
378a2f090 net_sched: Add qd... |
238 |
return NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; |
4c30719f4 [PKT_SCHED] dsmar... |
239 |
|
f6853e2df [NET_SCHED]: sch_... |
240 |
case TC_ACT_SHOT: |
4c30719f4 [PKT_SCHED] dsmar... |
241 |
goto drop; |
1da177e4c Linux-2.6.12-rc2 |
242 |
#endif |
c3bc7cff8 [NET_SCHED]: Kill... |
243 |
case TC_ACT_OK: |
f6853e2df [NET_SCHED]: sch_... |
244 245 |
skb->tc_index = TC_H_MIN(res.classid); break; |
4c30719f4 [PKT_SCHED] dsmar... |
246 |
|
f6853e2df [NET_SCHED]: sch_... |
247 248 249 250 |
default: if (p->default_index != NO_DEFAULT_INDEX) skb->tc_index = p->default_index; break; |
3ff50b799 [NET]: cleanup ex... |
251 |
} |
1da177e4c Linux-2.6.12-rc2 |
252 |
} |
1da177e4c Linux-2.6.12-rc2 |
253 |
|
520ac30f4 net_sched: drop p... |
254 |
err = qdisc_enqueue(skb, p->q, to_free); |
af0d11417 [PKT_SCHED]: Logi... |
255 |
if (err != NET_XMIT_SUCCESS) { |
378a2f090 net_sched: Add qd... |
256 |
if (net_xmit_drop_count(err)) |
25331d6ce net: sched: imple... |
257 |
qdisc_qstats_drop(sch); |
af0d11417 [PKT_SCHED]: Logi... |
258 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
259 |
} |
af0d11417 [PKT_SCHED]: Logi... |
260 |
|
f6bab1993 sched: Avoid dere... |
261 |
sch->qstats.backlog += len; |
1da177e4c Linux-2.6.12-rc2 |
262 |
sch->q.qlen++; |
1da177e4c Linux-2.6.12-rc2 |
263 |
|
af0d11417 [PKT_SCHED]: Logi... |
264 |
return NET_XMIT_SUCCESS; |
4c30719f4 [PKT_SCHED] dsmar... |
265 266 |
drop: |
520ac30f4 net_sched: drop p... |
267 |
qdisc_drop(skb, sch, to_free); |
c27f339af net_sched: Add qd... |
268 |
return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; |
af0d11417 [PKT_SCHED]: Logi... |
269 |
} |
1da177e4c Linux-2.6.12-rc2 |
270 271 272 |
static struct sk_buff *dsmark_dequeue(struct Qdisc *sch) { |
81da99ed7 [PKT_SCHED] dsmar... |
273 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
1da177e4c Linux-2.6.12-rc2 |
274 |
struct sk_buff *skb; |
af0d11417 [PKT_SCHED]: Logi... |
275 |
u32 index; |
c76f2a2c4 sch_dsmark: use c... |
276 277 |
pr_debug("%s(sch %p,[qdisc %p]) ", __func__, sch, p); |
1da177e4c Linux-2.6.12-rc2 |
278 |
|
f8b33d8e8 net_sched: dsmark... |
279 |
skb = qdisc_dequeue_peeked(p->q); |
af0d11417 [PKT_SCHED]: Logi... |
280 |
if (skb == NULL) |
1da177e4c Linux-2.6.12-rc2 |
281 |
return NULL; |
af0d11417 [PKT_SCHED]: Logi... |
282 |
|
9190b3b32 net_sched: accura... |
283 |
qdisc_bstats_update(sch, skb); |
bdf17661f sch_dsmark: updat... |
284 |
qdisc_qstats_backlog_dec(sch, skb); |
1da177e4c Linux-2.6.12-rc2 |
285 |
sch->q.qlen--; |
af0d11417 [PKT_SCHED]: Logi... |
286 287 |
index = skb->tc_index & (p->indices - 1); |
81da99ed7 [PKT_SCHED] dsmar... |
288 289 |
pr_debug("index %d->%d ", skb->tc_index, index); |
af0d11417 [PKT_SCHED]: Logi... |
290 |
|
d7bf2ebeb sched: consistent... |
291 |
switch (skb_protocol(skb, true)) { |
606780404 net: Use hton[sl]... |
292 |
case htons(ETH_P_IP): |
47bbbb30b sch_dsmark: impro... |
293 294 |
ipv4_change_dsfield(ip_hdr(skb), p->mv[index].mask, p->mv[index].value); |
1da177e4c Linux-2.6.12-rc2 |
295 |
break; |
606780404 net: Use hton[sl]... |
296 |
case htons(ETH_P_IPV6): |
47bbbb30b sch_dsmark: impro... |
297 298 |
ipv6_change_dsfield(ipv6_hdr(skb), p->mv[index].mask, p->mv[index].value); |
1da177e4c Linux-2.6.12-rc2 |
299 |
break; |
9d127fbdd [PKT_SCHED] dsmar... |
300 301 302 303 304 305 |
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. */ |
47bbbb30b sch_dsmark: impro... |
306 |
if (p->mv[index].mask != 0xff || p->mv[index].value) |
c76f2a2c4 sch_dsmark: use c... |
307 308 |
pr_warn("%s: unsupported protocol %d ", |
d7bf2ebeb sched: consistent... |
309 |
__func__, ntohs(skb_protocol(skb, true))); |
9d127fbdd [PKT_SCHED] dsmar... |
310 |
break; |
3ff50b799 [NET]: cleanup ex... |
311 |
} |
af0d11417 [PKT_SCHED]: Logi... |
312 |
|
1da177e4c Linux-2.6.12-rc2 |
313 314 |
return skb; } |
8e3af9789 pkt_sched: Add qd... |
315 316 317 |
static struct sk_buff *dsmark_peek(struct Qdisc *sch) { struct dsmark_qdisc_data *p = qdisc_priv(sch); |
c76f2a2c4 sch_dsmark: use c... |
318 319 |
pr_debug("%s(sch %p,[qdisc %p]) ", __func__, sch, p); |
8e3af9789 pkt_sched: Add qd... |
320 321 322 |
return p->q->ops->peek(p->q); } |
e63d7dfd2 net: sched: sch: ... |
323 324 |
static int dsmark_init(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) |
1da177e4c Linux-2.6.12-rc2 |
325 |
{ |
81da99ed7 [PKT_SCHED] dsmar... |
326 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
1e90474c3 [NET_SCHED]: Conv... |
327 |
struct nlattr *tb[TCA_DSMARK_MAX + 1]; |
9d4f97f97 sch_dsmark: Fix u... |
328 |
int err = -EINVAL; |
758cc43c6 [PKT_SCHED]: Fix ... |
329 330 |
u32 default_index = NO_DEFAULT_INDEX; u16 indices; |
47bbbb30b sch_dsmark: impro... |
331 |
int i; |
758cc43c6 [PKT_SCHED]: Fix ... |
332 |
|
c76f2a2c4 sch_dsmark: use c... |
333 334 |
pr_debug("%s(sch %p,[qdisc %p],opt %p) ", __func__, sch, p, opt); |
758cc43c6 [PKT_SCHED]: Fix ... |
335 |
|
cee63723b [NET_SCHED]: Prop... |
336 337 |
if (!opt) goto errout; |
8d1a77f97 net: sch: api: ad... |
338 |
err = tcf_block_get(&p->block, &p->filter_list, sch, extack); |
6529eaba3 net: sched: intro... |
339 340 |
if (err) return err; |
8cb081746 netlink: make val... |
341 342 |
err = nla_parse_nested_deprecated(tb, TCA_DSMARK_MAX, opt, dsmark_policy, NULL); |
cee63723b [NET_SCHED]: Prop... |
343 |
if (err < 0) |
758cc43c6 [PKT_SCHED]: Fix ... |
344 |
goto errout; |
cee63723b [NET_SCHED]: Prop... |
345 |
err = -EINVAL; |
474f0813a sch_dsmark: fix p... |
346 347 |
if (!tb[TCA_DSMARK_INDICES]) goto errout; |
1e90474c3 [NET_SCHED]: Conv... |
348 |
indices = nla_get_u16(tb[TCA_DSMARK_INDICES]); |
5b0ac72bc [PKT_SCHED] dsmar... |
349 350 |
if (hweight32(indices) != 1) |
758cc43c6 [PKT_SCHED]: Fix ... |
351 |
goto errout; |
27a3421e4 [NET_SCHED]: Use ... |
352 |
if (tb[TCA_DSMARK_DEFAULT_INDEX]) |
1e90474c3 [NET_SCHED]: Conv... |
353 |
default_index = nla_get_u16(tb[TCA_DSMARK_DEFAULT_INDEX]); |
758cc43c6 [PKT_SCHED]: Fix ... |
354 |
|
47bbbb30b sch_dsmark: impro... |
355 356 357 358 359 |
if (indices <= DSMARK_EMBEDDED_SZ) p->mv = p->embedded; else p->mv = kmalloc_array(indices, sizeof(*p->mv), GFP_KERNEL); if (!p->mv) { |
758cc43c6 [PKT_SCHED]: Fix ... |
360 361 |
err = -ENOMEM; goto errout; |
1da177e4c Linux-2.6.12-rc2 |
362 |
} |
47bbbb30b sch_dsmark: impro... |
363 364 365 366 |
for (i = 0; i < indices; i++) { p->mv[i].mask = 0xff; p->mv[i].value = 0; } |
758cc43c6 [PKT_SCHED]: Fix ... |
367 368 |
p->indices = indices; p->default_index = default_index; |
1e90474c3 [NET_SCHED]: Conv... |
369 |
p->set_tc_index = nla_get_flag(tb[TCA_DSMARK_SET_TC_INDEX]); |
758cc43c6 [PKT_SCHED]: Fix ... |
370 |
|
a38a98821 net: sch: api: ad... |
371 372 |
p->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, sch->handle, NULL); |
758cc43c6 [PKT_SCHED]: Fix ... |
373 |
if (p->q == NULL) |
1da177e4c Linux-2.6.12-rc2 |
374 |
p->q = &noop_qdisc; |
49b499718 net: sched: make ... |
375 376 |
else qdisc_hash_add(p->q, true); |
758cc43c6 [PKT_SCHED]: Fix ... |
377 |
|
c76f2a2c4 sch_dsmark: use c... |
378 379 |
pr_debug("%s: qdisc %p ", __func__, p->q); |
758cc43c6 [PKT_SCHED]: Fix ... |
380 381 382 |
err = 0; errout: |
758cc43c6 [PKT_SCHED]: Fix ... |
383 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
384 |
} |
1da177e4c Linux-2.6.12-rc2 |
385 386 |
static void dsmark_reset(struct Qdisc *sch) { |
81da99ed7 [PKT_SCHED] dsmar... |
387 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
1da177e4c Linux-2.6.12-rc2 |
388 |
|
c76f2a2c4 sch_dsmark: use c... |
389 390 |
pr_debug("%s(sch %p,[qdisc %p]) ", __func__, sch, p); |
1da177e4c Linux-2.6.12-rc2 |
391 |
qdisc_reset(p->q); |
bdf17661f sch_dsmark: updat... |
392 |
sch->qstats.backlog = 0; |
1da177e4c Linux-2.6.12-rc2 |
393 394 |
sch->q.qlen = 0; } |
1da177e4c Linux-2.6.12-rc2 |
395 396 |
static void dsmark_destroy(struct Qdisc *sch) { |
81da99ed7 [PKT_SCHED] dsmar... |
397 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
1da177e4c Linux-2.6.12-rc2 |
398 |
|
c76f2a2c4 sch_dsmark: use c... |
399 400 |
pr_debug("%s(sch %p,[qdisc %p]) ", __func__, sch, p); |
af0d11417 [PKT_SCHED]: Logi... |
401 |
|
6529eaba3 net: sched: intro... |
402 |
tcf_block_put(p->block); |
86bd446b5 net: sched: renam... |
403 |
qdisc_put(p->q); |
47bbbb30b sch_dsmark: impro... |
404 405 |
if (p->mv != p->embedded) kfree(p->mv); |
1da177e4c Linux-2.6.12-rc2 |
406 |
} |
1da177e4c Linux-2.6.12-rc2 |
407 |
static int dsmark_dump_class(struct Qdisc *sch, unsigned long cl, |
02f23f095 [PKT_SCHED]: Make... |
408 |
struct sk_buff *skb, struct tcmsg *tcm) |
1da177e4c Linux-2.6.12-rc2 |
409 |
{ |
81da99ed7 [PKT_SCHED] dsmar... |
410 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
1e90474c3 [NET_SCHED]: Conv... |
411 |
struct nlattr *opts = NULL; |
1da177e4c Linux-2.6.12-rc2 |
412 |
|
c76f2a2c4 sch_dsmark: use c... |
413 414 |
pr_debug("%s(sch %p,[qdisc %p],class %ld ", __func__, sch, p, cl); |
02f23f095 [PKT_SCHED]: Make... |
415 416 |
if (!dsmark_valid_index(p, cl)) |
1da177e4c Linux-2.6.12-rc2 |
417 |
return -EINVAL; |
02f23f095 [PKT_SCHED]: Make... |
418 |
|
cc7ec456f net_sched: cleanups |
419 |
tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle), cl - 1); |
cdc7f8e36 [PKT_SCHED]: Dump... |
420 |
tcm->tcm_info = p->q->handle; |
02f23f095 [PKT_SCHED]: Make... |
421 |
|
ae0be8de9 netlink: make nla... |
422 |
opts = nla_nest_start_noflag(skb, TCA_OPTIONS); |
1e90474c3 [NET_SCHED]: Conv... |
423 424 |
if (opts == NULL) goto nla_put_failure; |
47bbbb30b sch_dsmark: impro... |
425 426 |
if (nla_put_u8(skb, TCA_DSMARK_MASK, p->mv[cl - 1].mask) || nla_put_u8(skb, TCA_DSMARK_VALUE, p->mv[cl - 1].value)) |
1b34ec43c pkt_sched: Stop u... |
427 |
goto nla_put_failure; |
02f23f095 [PKT_SCHED]: Make... |
428 |
|
1e90474c3 [NET_SCHED]: Conv... |
429 |
return nla_nest_end(skb, opts); |
1da177e4c Linux-2.6.12-rc2 |
430 |
|
1e90474c3 [NET_SCHED]: Conv... |
431 |
nla_put_failure: |
bc3ed28ca netlink: Improve ... |
432 433 |
nla_nest_cancel(skb, opts); return -EMSGSIZE; |
1da177e4c Linux-2.6.12-rc2 |
434 435 436 437 |
} static int dsmark_dump(struct Qdisc *sch, struct sk_buff *skb) { |
81da99ed7 [PKT_SCHED] dsmar... |
438 |
struct dsmark_qdisc_data *p = qdisc_priv(sch); |
1e90474c3 [NET_SCHED]: Conv... |
439 |
struct nlattr *opts = NULL; |
1da177e4c Linux-2.6.12-rc2 |
440 |
|
ae0be8de9 netlink: make nla... |
441 |
opts = nla_nest_start_noflag(skb, TCA_OPTIONS); |
1e90474c3 [NET_SCHED]: Conv... |
442 443 |
if (opts == NULL) goto nla_put_failure; |
1b34ec43c pkt_sched: Stop u... |
444 445 |
if (nla_put_u16(skb, TCA_DSMARK_INDICES, p->indices)) goto nla_put_failure; |
02f23f095 [PKT_SCHED]: Make... |
446 |
|
1b34ec43c pkt_sched: Stop u... |
447 448 449 |
if (p->default_index != NO_DEFAULT_INDEX && nla_put_u16(skb, TCA_DSMARK_DEFAULT_INDEX, p->default_index)) goto nla_put_failure; |
1da177e4c Linux-2.6.12-rc2 |
450 |
|
1b34ec43c pkt_sched: Stop u... |
451 452 453 |
if (p->set_tc_index && nla_put_flag(skb, TCA_DSMARK_SET_TC_INDEX)) goto nla_put_failure; |
02f23f095 [PKT_SCHED]: Make... |
454 |
|
1e90474c3 [NET_SCHED]: Conv... |
455 |
return nla_nest_end(skb, opts); |
1da177e4c Linux-2.6.12-rc2 |
456 |
|
1e90474c3 [NET_SCHED]: Conv... |
457 |
nla_put_failure: |
bc3ed28ca netlink: Improve ... |
458 459 |
nla_nest_cancel(skb, opts); return -EMSGSIZE; |
1da177e4c Linux-2.6.12-rc2 |
460 |
} |
20fea08b5 [NET]: Move Qdisc... |
461 |
static const struct Qdisc_class_ops dsmark_class_ops = { |
1da177e4c Linux-2.6.12-rc2 |
462 463 |
.graft = dsmark_graft, .leaf = dsmark_leaf, |
143976ce9 net_sched: remove... |
464 |
.find = dsmark_find, |
1da177e4c Linux-2.6.12-rc2 |
465 466 467 |
.change = dsmark_change, .delete = dsmark_delete, .walk = dsmark_walk, |
6529eaba3 net: sched: intro... |
468 |
.tcf_block = dsmark_tcf_block, |
1da177e4c Linux-2.6.12-rc2 |
469 |
.bind_tcf = dsmark_bind_filter, |
143976ce9 net_sched: remove... |
470 |
.unbind_tcf = dsmark_unbind_filter, |
1da177e4c Linux-2.6.12-rc2 |
471 472 |
.dump = dsmark_dump_class, }; |
20fea08b5 [NET]: Move Qdisc... |
473 |
static struct Qdisc_ops dsmark_qdisc_ops __read_mostly = { |
1da177e4c Linux-2.6.12-rc2 |
474 475 476 477 478 479 |
.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... |
480 |
.peek = dsmark_peek, |
1da177e4c Linux-2.6.12-rc2 |
481 482 483 484 485 486 487 488 489 490 491 492 |
.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... |
493 |
|
10297b993 [NET] SCHED: Fix ... |
494 |
static void __exit dsmark_module_exit(void) |
1da177e4c Linux-2.6.12-rc2 |
495 496 497 |
{ unregister_qdisc(&dsmark_qdisc_ops); } |
af0d11417 [PKT_SCHED]: Logi... |
498 |
|
1da177e4c Linux-2.6.12-rc2 |
499 500 |
module_init(dsmark_module_init) module_exit(dsmark_module_exit) |
af0d11417 [PKT_SCHED]: Logi... |
501 |
|
1da177e4c Linux-2.6.12-rc2 |
502 |
MODULE_LICENSE("GPL"); |