diff options
Diffstat (limited to 'net/sched/sch_dsmark.c')
-rw-r--r-- | net/sched/sch_dsmark.c | 131 |
1 files changed, 82 insertions, 49 deletions
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index d8bd2a569c7c..66abf139f4bf 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c | |||
@@ -62,6 +62,21 @@ struct dsmark_qdisc_data { | |||
62 | int set_tc_index; | 62 | int set_tc_index; |
63 | }; | 63 | }; |
64 | 64 | ||
65 | static inline int dsmark_valid_indices(u16 indices) | ||
66 | { | ||
67 | while (indices != 1) { | ||
68 | if (indices & 1) | ||
69 | return 0; | ||
70 | indices >>= 1; | ||
71 | } | ||
72 | |||
73 | return 1; | ||
74 | } | ||
75 | |||
76 | static inline int dsmark_valid_index(struct dsmark_qdisc_data *p, u16 index) | ||
77 | { | ||
78 | return (index <= p->indices && index > 0); | ||
79 | } | ||
65 | 80 | ||
66 | /* ------------------------- Class/flow operations ------------------------- */ | 81 | /* ------------------------- Class/flow operations ------------------------- */ |
67 | 82 | ||
@@ -120,31 +135,39 @@ static void dsmark_put(struct Qdisc *sch, unsigned long cl) | |||
120 | 135 | ||
121 | 136 | ||
122 | static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent, | 137 | static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent, |
123 | struct rtattr **tca, unsigned long *arg) | 138 | struct rtattr **tca, unsigned long *arg) |
124 | { | 139 | { |
125 | struct dsmark_qdisc_data *p = PRIV(sch); | 140 | struct dsmark_qdisc_data *p = PRIV(sch); |
126 | struct rtattr *opt = tca[TCA_OPTIONS-1]; | 141 | struct rtattr *opt = tca[TCA_OPTIONS-1]; |
127 | struct rtattr *tb[TCA_DSMARK_MAX]; | 142 | struct rtattr *tb[TCA_DSMARK_MAX]; |
143 | int err = -EINVAL; | ||
144 | u8 mask = 0; | ||
128 | 145 | ||
129 | DPRINTK("dsmark_change(sch %p,[qdisc %p],classid %x,parent %x)," | 146 | DPRINTK("dsmark_change(sch %p,[qdisc %p],classid %x,parent %x)," |
130 | "arg 0x%lx\n",sch,p,classid,parent,*arg); | 147 | "arg 0x%lx\n", sch, p, classid, parent, *arg); |
131 | if (*arg > p->indices) | 148 | |
132 | return -ENOENT; | 149 | if (!dsmark_valid_index(p, *arg)) { |
133 | if (!opt || rtattr_parse_nested(tb, TCA_DSMARK_MAX, opt)) | 150 | err = -ENOENT; |
134 | return -EINVAL; | 151 | goto rtattr_failure; |
135 | if (tb[TCA_DSMARK_MASK-1]) { | ||
136 | if (!RTA_PAYLOAD(tb[TCA_DSMARK_MASK-1])) | ||
137 | return -EINVAL; | ||
138 | p->mask[*arg-1] = *(__u8 *) RTA_DATA(tb[TCA_DSMARK_MASK-1]); | ||
139 | } | ||
140 | if (tb[TCA_DSMARK_VALUE-1]) { | ||
141 | if (!RTA_PAYLOAD(tb[TCA_DSMARK_VALUE-1])) | ||
142 | return -EINVAL; | ||
143 | p->value[*arg-1] = *(__u8 *) RTA_DATA(tb[TCA_DSMARK_VALUE-1]); | ||
144 | } | 152 | } |
145 | return 0; | ||
146 | } | ||
147 | 153 | ||
154 | if (!opt || rtattr_parse_nested(tb, TCA_DSMARK_MAX, opt)) | ||
155 | goto rtattr_failure; | ||
156 | |||
157 | if (tb[TCA_DSMARK_MASK-1]) | ||
158 | mask = RTA_GET_U8(tb[TCA_DSMARK_MASK-1]); | ||
159 | |||
160 | if (tb[TCA_DSMARK_VALUE-1]) | ||
161 | p->value[*arg-1] = RTA_GET_U8(tb[TCA_DSMARK_VALUE-1]); | ||
162 | |||
163 | if (tb[TCA_DSMARK_MASK-1]) | ||
164 | p->mask[*arg-1] = mask; | ||
165 | |||
166 | err = 0; | ||
167 | |||
168 | rtattr_failure: | ||
169 | return err; | ||
170 | } | ||
148 | 171 | ||
149 | static int dsmark_delete(struct Qdisc *sch,unsigned long arg) | 172 | static int dsmark_delete(struct Qdisc *sch,unsigned long arg) |
150 | { | 173 | { |
@@ -328,43 +351,53 @@ static unsigned int dsmark_drop(struct Qdisc *sch) | |||
328 | } | 351 | } |
329 | 352 | ||
330 | 353 | ||
331 | static int dsmark_init(struct Qdisc *sch,struct rtattr *opt) | 354 | static int dsmark_init(struct Qdisc *sch, struct rtattr *opt) |
332 | { | 355 | { |
333 | struct dsmark_qdisc_data *p = PRIV(sch); | 356 | struct dsmark_qdisc_data *p = PRIV(sch); |
334 | struct rtattr *tb[TCA_DSMARK_MAX]; | 357 | struct rtattr *tb[TCA_DSMARK_MAX]; |
335 | __u16 tmp; | 358 | int err = -EINVAL; |
336 | 359 | u32 default_index = NO_DEFAULT_INDEX; | |
337 | DPRINTK("dsmark_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt); | 360 | u16 indices; |
338 | if (!opt || | 361 | u8 *mask; |
339 | rtattr_parse(tb,TCA_DSMARK_MAX,RTA_DATA(opt),RTA_PAYLOAD(opt)) < 0 || | 362 | |
340 | !tb[TCA_DSMARK_INDICES-1] || | 363 | DPRINTK("dsmark_init(sch %p,[qdisc %p],opt %p)\n", sch, p, opt); |
341 | RTA_PAYLOAD(tb[TCA_DSMARK_INDICES-1]) < sizeof(__u16)) | 364 | |
342 | return -EINVAL; | 365 | if (!opt || rtattr_parse_nested(tb, TCA_DSMARK_MAX, opt) < 0) |
343 | p->indices = *(__u16 *) RTA_DATA(tb[TCA_DSMARK_INDICES-1]); | 366 | goto errout; |
344 | if (!p->indices) | 367 | |
345 | return -EINVAL; | 368 | indices = RTA_GET_U16(tb[TCA_DSMARK_INDICES-1]); |
346 | for (tmp = p->indices; tmp != 1; tmp >>= 1) { | 369 | if (!indices || !dsmark_valid_indices(indices)) |
347 | if (tmp & 1) | 370 | goto errout; |
348 | return -EINVAL; | 371 | |
349 | } | 372 | if (tb[TCA_DSMARK_DEFAULT_INDEX-1]) |
350 | p->default_index = NO_DEFAULT_INDEX; | 373 | default_index = RTA_GET_U16(tb[TCA_DSMARK_DEFAULT_INDEX-1]); |
351 | if (tb[TCA_DSMARK_DEFAULT_INDEX-1]) { | 374 | |
352 | if (RTA_PAYLOAD(tb[TCA_DSMARK_DEFAULT_INDEX-1]) < sizeof(__u16)) | 375 | mask = kmalloc(indices * 2, GFP_KERNEL); |
353 | return -EINVAL; | 376 | if (mask == NULL) { |
354 | p->default_index = | 377 | err = -ENOMEM; |
355 | *(__u16 *) RTA_DATA(tb[TCA_DSMARK_DEFAULT_INDEX-1]); | 378 | goto errout; |
356 | } | 379 | } |
357 | p->set_tc_index = !!tb[TCA_DSMARK_SET_TC_INDEX-1]; | 380 | |
358 | p->mask = kmalloc(p->indices*2,GFP_KERNEL); | 381 | p->mask = mask; |
359 | if (!p->mask) | 382 | memset(p->mask, 0xff, indices); |
360 | return -ENOMEM; | 383 | |
361 | p->value = p->mask+p->indices; | 384 | p->value = p->mask + indices; |
362 | memset(p->mask,0xff,p->indices); | 385 | memset(p->value, 0, indices); |
363 | memset(p->value,0,p->indices); | 386 | |
364 | if (!(p->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops))) | 387 | p->indices = indices; |
388 | p->default_index = default_index; | ||
389 | p->set_tc_index = RTA_GET_FLAG(tb[TCA_DSMARK_SET_TC_INDEX-1]); | ||
390 | |||
391 | p->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); | ||
392 | if (p->q == NULL) | ||
365 | p->q = &noop_qdisc; | 393 | p->q = &noop_qdisc; |
366 | DPRINTK("dsmark_init: qdisc %p\n",&p->q); | 394 | |
367 | return 0; | 395 | DPRINTK("dsmark_init: qdisc %p\n", p->q); |
396 | |||
397 | err = 0; | ||
398 | errout: | ||
399 | rtattr_failure: | ||
400 | return err; | ||
368 | } | 401 | } |
369 | 402 | ||
370 | 403 | ||