diff options
Diffstat (limited to 'net/sched/sch_tbf.c')
-rw-r--r-- | net/sched/sch_tbf.c | 68 |
1 files changed, 39 insertions, 29 deletions
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index b0d81098b0ee..0b7d78f59d8c 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c | |||
@@ -245,20 +245,21 @@ static void tbf_reset(struct Qdisc* sch) | |||
245 | static struct Qdisc *tbf_create_dflt_qdisc(struct Qdisc *sch, u32 limit) | 245 | static struct Qdisc *tbf_create_dflt_qdisc(struct Qdisc *sch, u32 limit) |
246 | { | 246 | { |
247 | struct Qdisc *q; | 247 | struct Qdisc *q; |
248 | struct rtattr *rta; | 248 | struct nlattr *nla; |
249 | int ret; | 249 | int ret; |
250 | 250 | ||
251 | q = qdisc_create_dflt(sch->dev, &bfifo_qdisc_ops, | 251 | q = qdisc_create_dflt(sch->dev, &bfifo_qdisc_ops, |
252 | TC_H_MAKE(sch->handle, 1)); | 252 | TC_H_MAKE(sch->handle, 1)); |
253 | if (q) { | 253 | if (q) { |
254 | rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL); | 254 | nla = kmalloc(nla_attr_size(sizeof(struct tc_fifo_qopt)), |
255 | if (rta) { | 255 | GFP_KERNEL); |
256 | rta->rta_type = RTM_NEWQDISC; | 256 | if (nla) { |
257 | rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt)); | 257 | nla->nla_type = RTM_NEWQDISC; |
258 | ((struct tc_fifo_qopt *)RTA_DATA(rta))->limit = limit; | 258 | nla->nla_len = nla_attr_size(sizeof(struct tc_fifo_qopt)); |
259 | ((struct tc_fifo_qopt *)nla_data(nla))->limit = limit; | ||
259 | 260 | ||
260 | ret = q->ops->change(q, rta); | 261 | ret = q->ops->change(q, nla); |
261 | kfree(rta); | 262 | kfree(nla); |
262 | 263 | ||
263 | if (ret == 0) | 264 | if (ret == 0) |
264 | return q; | 265 | return q; |
@@ -269,30 +270,39 @@ static struct Qdisc *tbf_create_dflt_qdisc(struct Qdisc *sch, u32 limit) | |||
269 | return NULL; | 270 | return NULL; |
270 | } | 271 | } |
271 | 272 | ||
272 | static int tbf_change(struct Qdisc* sch, struct rtattr *opt) | 273 | static const struct nla_policy tbf_policy[TCA_TBF_MAX + 1] = { |
274 | [TCA_TBF_PARMS] = { .len = sizeof(struct tc_tbf_qopt) }, | ||
275 | [TCA_TBF_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, | ||
276 | [TCA_TBF_PTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, | ||
277 | }; | ||
278 | |||
279 | static int tbf_change(struct Qdisc* sch, struct nlattr *opt) | ||
273 | { | 280 | { |
274 | int err = -EINVAL; | 281 | int err; |
275 | struct tbf_sched_data *q = qdisc_priv(sch); | 282 | struct tbf_sched_data *q = qdisc_priv(sch); |
276 | struct rtattr *tb[TCA_TBF_PTAB]; | 283 | struct nlattr *tb[TCA_TBF_PTAB + 1]; |
277 | struct tc_tbf_qopt *qopt; | 284 | struct tc_tbf_qopt *qopt; |
278 | struct qdisc_rate_table *rtab = NULL; | 285 | struct qdisc_rate_table *rtab = NULL; |
279 | struct qdisc_rate_table *ptab = NULL; | 286 | struct qdisc_rate_table *ptab = NULL; |
280 | struct Qdisc *child = NULL; | 287 | struct Qdisc *child = NULL; |
281 | int max_size,n; | 288 | int max_size,n; |
282 | 289 | ||
283 | if (rtattr_parse_nested(tb, TCA_TBF_PTAB, opt) || | 290 | err = nla_parse_nested(tb, TCA_TBF_PTAB, opt, tbf_policy); |
284 | tb[TCA_TBF_PARMS-1] == NULL || | 291 | if (err < 0) |
285 | RTA_PAYLOAD(tb[TCA_TBF_PARMS-1]) < sizeof(*qopt)) | 292 | return err; |
293 | |||
294 | err = -EINVAL; | ||
295 | if (tb[TCA_TBF_PARMS] == NULL) | ||
286 | goto done; | 296 | goto done; |
287 | 297 | ||
288 | qopt = RTA_DATA(tb[TCA_TBF_PARMS-1]); | 298 | qopt = nla_data(tb[TCA_TBF_PARMS]); |
289 | rtab = qdisc_get_rtab(&qopt->rate, tb[TCA_TBF_RTAB-1]); | 299 | rtab = qdisc_get_rtab(&qopt->rate, tb[TCA_TBF_RTAB]); |
290 | if (rtab == NULL) | 300 | if (rtab == NULL) |
291 | goto done; | 301 | goto done; |
292 | 302 | ||
293 | if (qopt->peakrate.rate) { | 303 | if (qopt->peakrate.rate) { |
294 | if (qopt->peakrate.rate > qopt->rate.rate) | 304 | if (qopt->peakrate.rate > qopt->rate.rate) |
295 | ptab = qdisc_get_rtab(&qopt->peakrate, tb[TCA_TBF_PTAB-1]); | 305 | ptab = qdisc_get_rtab(&qopt->peakrate, tb[TCA_TBF_PTAB]); |
296 | if (ptab == NULL) | 306 | if (ptab == NULL) |
297 | goto done; | 307 | goto done; |
298 | } | 308 | } |
@@ -339,7 +349,7 @@ done: | |||
339 | return err; | 349 | return err; |
340 | } | 350 | } |
341 | 351 | ||
342 | static int tbf_init(struct Qdisc* sch, struct rtattr *opt) | 352 | static int tbf_init(struct Qdisc* sch, struct nlattr *opt) |
343 | { | 353 | { |
344 | struct tbf_sched_data *q = qdisc_priv(sch); | 354 | struct tbf_sched_data *q = qdisc_priv(sch); |
345 | 355 | ||
@@ -370,12 +380,12 @@ static void tbf_destroy(struct Qdisc *sch) | |||
370 | static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb) | 380 | static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb) |
371 | { | 381 | { |
372 | struct tbf_sched_data *q = qdisc_priv(sch); | 382 | struct tbf_sched_data *q = qdisc_priv(sch); |
373 | unsigned char *b = skb_tail_pointer(skb); | 383 | struct nlattr *nest; |
374 | struct rtattr *rta; | ||
375 | struct tc_tbf_qopt opt; | 384 | struct tc_tbf_qopt opt; |
376 | 385 | ||
377 | rta = (struct rtattr*)b; | 386 | nest = nla_nest_start(skb, TCA_OPTIONS); |
378 | RTA_PUT(skb, TCA_OPTIONS, 0, NULL); | 387 | if (nest == NULL) |
388 | goto nla_put_failure; | ||
379 | 389 | ||
380 | opt.limit = q->limit; | 390 | opt.limit = q->limit; |
381 | opt.rate = q->R_tab->rate; | 391 | opt.rate = q->R_tab->rate; |
@@ -385,13 +395,13 @@ static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
385 | memset(&opt.peakrate, 0, sizeof(opt.peakrate)); | 395 | memset(&opt.peakrate, 0, sizeof(opt.peakrate)); |
386 | opt.mtu = q->mtu; | 396 | opt.mtu = q->mtu; |
387 | opt.buffer = q->buffer; | 397 | opt.buffer = q->buffer; |
388 | RTA_PUT(skb, TCA_TBF_PARMS, sizeof(opt), &opt); | 398 | NLA_PUT(skb, TCA_TBF_PARMS, sizeof(opt), &opt); |
389 | rta->rta_len = skb_tail_pointer(skb) - b; | ||
390 | 399 | ||
400 | nla_nest_end(skb, nest); | ||
391 | return skb->len; | 401 | return skb->len; |
392 | 402 | ||
393 | rtattr_failure: | 403 | nla_put_failure: |
394 | nlmsg_trim(skb, b); | 404 | nla_nest_cancel(skb, nest); |
395 | return -1; | 405 | return -1; |
396 | } | 406 | } |
397 | 407 | ||
@@ -442,7 +452,7 @@ static void tbf_put(struct Qdisc *sch, unsigned long arg) | |||
442 | } | 452 | } |
443 | 453 | ||
444 | static int tbf_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | 454 | static int tbf_change_class(struct Qdisc *sch, u32 classid, u32 parentid, |
445 | struct rtattr **tca, unsigned long *arg) | 455 | struct nlattr **tca, unsigned long *arg) |
446 | { | 456 | { |
447 | return -ENOSYS; | 457 | return -ENOSYS; |
448 | } | 458 | } |
@@ -469,7 +479,7 @@ static struct tcf_proto **tbf_find_tcf(struct Qdisc *sch, unsigned long cl) | |||
469 | return NULL; | 479 | return NULL; |
470 | } | 480 | } |
471 | 481 | ||
472 | static struct Qdisc_class_ops tbf_class_ops = | 482 | static const struct Qdisc_class_ops tbf_class_ops = |
473 | { | 483 | { |
474 | .graft = tbf_graft, | 484 | .graft = tbf_graft, |
475 | .leaf = tbf_leaf, | 485 | .leaf = tbf_leaf, |
@@ -482,7 +492,7 @@ static struct Qdisc_class_ops tbf_class_ops = | |||
482 | .dump = tbf_dump_class, | 492 | .dump = tbf_dump_class, |
483 | }; | 493 | }; |
484 | 494 | ||
485 | static struct Qdisc_ops tbf_qdisc_ops = { | 495 | static struct Qdisc_ops tbf_qdisc_ops __read_mostly = { |
486 | .next = NULL, | 496 | .next = NULL, |
487 | .cl_ops = &tbf_class_ops, | 497 | .cl_ops = &tbf_class_ops, |
488 | .id = "tbf", | 498 | .id = "tbf", |