aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/cls_u32.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched/cls_u32.c')
-rw-r--r--net/sched/cls_u32.c103
1 files changed, 53 insertions, 50 deletions
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index c39008209164..e8a775689123 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -460,10 +460,20 @@ static u32 gen_new_kid(struct tc_u_hnode *ht, u32 handle)
460 return handle|(i>0xFFF ? 0xFFF : i); 460 return handle|(i>0xFFF ? 0xFFF : i);
461} 461}
462 462
463static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = {
464 [TCA_U32_CLASSID] = { .type = NLA_U32 },
465 [TCA_U32_HASH] = { .type = NLA_U32 },
466 [TCA_U32_LINK] = { .type = NLA_U32 },
467 [TCA_U32_DIVISOR] = { .type = NLA_U32 },
468 [TCA_U32_SEL] = { .len = sizeof(struct tc_u32_sel) },
469 [TCA_U32_INDEV] = { .type = NLA_STRING, .len = IFNAMSIZ },
470 [TCA_U32_MARK] = { .len = sizeof(struct tc_u32_mark) },
471};
472
463static int u32_set_parms(struct tcf_proto *tp, unsigned long base, 473static int u32_set_parms(struct tcf_proto *tp, unsigned long base,
464 struct tc_u_hnode *ht, 474 struct tc_u_hnode *ht,
465 struct tc_u_knode *n, struct rtattr **tb, 475 struct tc_u_knode *n, struct nlattr **tb,
466 struct rtattr *est) 476 struct nlattr *est)
467{ 477{
468 int err; 478 int err;
469 struct tcf_exts e; 479 struct tcf_exts e;
@@ -473,8 +483,8 @@ static int u32_set_parms(struct tcf_proto *tp, unsigned long base,
473 return err; 483 return err;
474 484
475 err = -EINVAL; 485 err = -EINVAL;
476 if (tb[TCA_U32_LINK-1]) { 486 if (tb[TCA_U32_LINK]) {
477 u32 handle = *(u32*)RTA_DATA(tb[TCA_U32_LINK-1]); 487 u32 handle = nla_get_u32(tb[TCA_U32_LINK]);
478 struct tc_u_hnode *ht_down = NULL; 488 struct tc_u_hnode *ht_down = NULL;
479 489
480 if (TC_U32_KEY(handle)) 490 if (TC_U32_KEY(handle))
@@ -495,14 +505,14 @@ static int u32_set_parms(struct tcf_proto *tp, unsigned long base,
495 if (ht_down) 505 if (ht_down)
496 ht_down->refcnt--; 506 ht_down->refcnt--;
497 } 507 }
498 if (tb[TCA_U32_CLASSID-1]) { 508 if (tb[TCA_U32_CLASSID]) {
499 n->res.classid = *(u32*)RTA_DATA(tb[TCA_U32_CLASSID-1]); 509 n->res.classid = nla_get_u32(tb[TCA_U32_CLASSID]);
500 tcf_bind_filter(tp, &n->res, base); 510 tcf_bind_filter(tp, &n->res, base);
501 } 511 }
502 512
503#ifdef CONFIG_NET_CLS_IND 513#ifdef CONFIG_NET_CLS_IND
504 if (tb[TCA_U32_INDEV-1]) { 514 if (tb[TCA_U32_INDEV]) {
505 err = tcf_change_indev(tp, n->indev, tb[TCA_U32_INDEV-1]); 515 err = tcf_change_indev(tp, n->indev, tb[TCA_U32_INDEV]);
506 if (err < 0) 516 if (err < 0)
507 goto errout; 517 goto errout;
508 } 518 }
@@ -516,33 +526,34 @@ errout:
516} 526}
517 527
518static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle, 528static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
519 struct rtattr **tca, 529 struct nlattr **tca,
520 unsigned long *arg) 530 unsigned long *arg)
521{ 531{
522 struct tc_u_common *tp_c = tp->data; 532 struct tc_u_common *tp_c = tp->data;
523 struct tc_u_hnode *ht; 533 struct tc_u_hnode *ht;
524 struct tc_u_knode *n; 534 struct tc_u_knode *n;
525 struct tc_u32_sel *s; 535 struct tc_u32_sel *s;
526 struct rtattr *opt = tca[TCA_OPTIONS-1]; 536 struct nlattr *opt = tca[TCA_OPTIONS];
527 struct rtattr *tb[TCA_U32_MAX]; 537 struct nlattr *tb[TCA_U32_MAX + 1];
528 u32 htid; 538 u32 htid;
529 int err; 539 int err;
530 540
531 if (opt == NULL) 541 if (opt == NULL)
532 return handle ? -EINVAL : 0; 542 return handle ? -EINVAL : 0;
533 543
534 if (rtattr_parse_nested(tb, TCA_U32_MAX, opt) < 0) 544 err = nla_parse_nested(tb, TCA_U32_MAX, opt, u32_policy);
535 return -EINVAL; 545 if (err < 0)
546 return err;
536 547
537 if ((n = (struct tc_u_knode*)*arg) != NULL) { 548 if ((n = (struct tc_u_knode*)*arg) != NULL) {
538 if (TC_U32_KEY(n->handle) == 0) 549 if (TC_U32_KEY(n->handle) == 0)
539 return -EINVAL; 550 return -EINVAL;
540 551
541 return u32_set_parms(tp, base, n->ht_up, n, tb, tca[TCA_RATE-1]); 552 return u32_set_parms(tp, base, n->ht_up, n, tb, tca[TCA_RATE]);
542 } 553 }
543 554
544 if (tb[TCA_U32_DIVISOR-1]) { 555 if (tb[TCA_U32_DIVISOR]) {
545 unsigned divisor = *(unsigned*)RTA_DATA(tb[TCA_U32_DIVISOR-1]); 556 unsigned divisor = nla_get_u32(tb[TCA_U32_DIVISOR]);
546 557
547 if (--divisor > 0x100) 558 if (--divisor > 0x100)
548 return -EINVAL; 559 return -EINVAL;
@@ -567,8 +578,8 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
567 return 0; 578 return 0;
568 } 579 }
569 580
570 if (tb[TCA_U32_HASH-1]) { 581 if (tb[TCA_U32_HASH]) {
571 htid = *(unsigned*)RTA_DATA(tb[TCA_U32_HASH-1]); 582 htid = nla_get_u32(tb[TCA_U32_HASH]);
572 if (TC_U32_HTID(htid) == TC_U32_ROOT) { 583 if (TC_U32_HTID(htid) == TC_U32_ROOT) {
573 ht = tp->root; 584 ht = tp->root;
574 htid = ht->handle; 585 htid = ht->handle;
@@ -592,11 +603,10 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
592 } else 603 } else
593 handle = gen_new_kid(ht, htid); 604 handle = gen_new_kid(ht, htid);
594 605
595 if (tb[TCA_U32_SEL-1] == NULL || 606 if (tb[TCA_U32_SEL] == NULL)
596 RTA_PAYLOAD(tb[TCA_U32_SEL-1]) < sizeof(struct tc_u32_sel))
597 return -EINVAL; 607 return -EINVAL;
598 608
599 s = RTA_DATA(tb[TCA_U32_SEL-1]); 609 s = nla_data(tb[TCA_U32_SEL]);
600 610
601 n = kzalloc(sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key), GFP_KERNEL); 611 n = kzalloc(sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key), GFP_KERNEL);
602 if (n == NULL) 612 if (n == NULL)
@@ -616,23 +626,16 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
616 n->fshift = s->hmask ? ffs(ntohl(s->hmask)) - 1 : 0; 626 n->fshift = s->hmask ? ffs(ntohl(s->hmask)) - 1 : 0;
617 627
618#ifdef CONFIG_CLS_U32_MARK 628#ifdef CONFIG_CLS_U32_MARK
619 if (tb[TCA_U32_MARK-1]) { 629 if (tb[TCA_U32_MARK]) {
620 struct tc_u32_mark *mark; 630 struct tc_u32_mark *mark;
621 631
622 if (RTA_PAYLOAD(tb[TCA_U32_MARK-1]) < sizeof(struct tc_u32_mark)) { 632 mark = nla_data(tb[TCA_U32_MARK]);
623#ifdef CONFIG_CLS_U32_PERF
624 kfree(n->pf);
625#endif
626 kfree(n);
627 return -EINVAL;
628 }
629 mark = RTA_DATA(tb[TCA_U32_MARK-1]);
630 memcpy(&n->mark, mark, sizeof(struct tc_u32_mark)); 633 memcpy(&n->mark, mark, sizeof(struct tc_u32_mark));
631 n->mark.success = 0; 634 n->mark.success = 0;
632 } 635 }
633#endif 636#endif
634 637
635 err = u32_set_parms(tp, base, ht, n, tb, tca[TCA_RATE-1]); 638 err = u32_set_parms(tp, base, ht, n, tb, tca[TCA_RATE]);
636 if (err == 0) { 639 if (err == 0) {
637 struct tc_u_knode **ins; 640 struct tc_u_knode **ins;
638 for (ins = &ht->ht[TC_U32_HASH(handle)]; *ins; ins = &(*ins)->next) 641 for (ins = &ht->ht[TC_U32_HASH(handle)]; *ins; ins = &(*ins)->next)
@@ -693,66 +696,66 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh,
693 struct sk_buff *skb, struct tcmsg *t) 696 struct sk_buff *skb, struct tcmsg *t)
694{ 697{
695 struct tc_u_knode *n = (struct tc_u_knode*)fh; 698 struct tc_u_knode *n = (struct tc_u_knode*)fh;
696 unsigned char *b = skb_tail_pointer(skb); 699 struct nlattr *nest;
697 struct rtattr *rta;
698 700
699 if (n == NULL) 701 if (n == NULL)
700 return skb->len; 702 return skb->len;
701 703
702 t->tcm_handle = n->handle; 704 t->tcm_handle = n->handle;
703 705
704 rta = (struct rtattr*)b; 706 nest = nla_nest_start(skb, TCA_OPTIONS);
705 RTA_PUT(skb, TCA_OPTIONS, 0, NULL); 707 if (nest == NULL)
708 goto nla_put_failure;
706 709
707 if (TC_U32_KEY(n->handle) == 0) { 710 if (TC_U32_KEY(n->handle) == 0) {
708 struct tc_u_hnode *ht = (struct tc_u_hnode*)fh; 711 struct tc_u_hnode *ht = (struct tc_u_hnode*)fh;
709 u32 divisor = ht->divisor+1; 712 u32 divisor = ht->divisor+1;
710 RTA_PUT(skb, TCA_U32_DIVISOR, 4, &divisor); 713 NLA_PUT_U32(skb, TCA_U32_DIVISOR, divisor);
711 } else { 714 } else {
712 RTA_PUT(skb, TCA_U32_SEL, 715 NLA_PUT(skb, TCA_U32_SEL,
713 sizeof(n->sel) + n->sel.nkeys*sizeof(struct tc_u32_key), 716 sizeof(n->sel) + n->sel.nkeys*sizeof(struct tc_u32_key),
714 &n->sel); 717 &n->sel);
715 if (n->ht_up) { 718 if (n->ht_up) {
716 u32 htid = n->handle & 0xFFFFF000; 719 u32 htid = n->handle & 0xFFFFF000;
717 RTA_PUT(skb, TCA_U32_HASH, 4, &htid); 720 NLA_PUT_U32(skb, TCA_U32_HASH, htid);
718 } 721 }
719 if (n->res.classid) 722 if (n->res.classid)
720 RTA_PUT(skb, TCA_U32_CLASSID, 4, &n->res.classid); 723 NLA_PUT_U32(skb, TCA_U32_CLASSID, n->res.classid);
721 if (n->ht_down) 724 if (n->ht_down)
722 RTA_PUT(skb, TCA_U32_LINK, 4, &n->ht_down->handle); 725 NLA_PUT_U32(skb, TCA_U32_LINK, n->ht_down->handle);
723 726
724#ifdef CONFIG_CLS_U32_MARK 727#ifdef CONFIG_CLS_U32_MARK
725 if (n->mark.val || n->mark.mask) 728 if (n->mark.val || n->mark.mask)
726 RTA_PUT(skb, TCA_U32_MARK, sizeof(n->mark), &n->mark); 729 NLA_PUT(skb, TCA_U32_MARK, sizeof(n->mark), &n->mark);
727#endif 730#endif
728 731
729 if (tcf_exts_dump(skb, &n->exts, &u32_ext_map) < 0) 732 if (tcf_exts_dump(skb, &n->exts, &u32_ext_map) < 0)
730 goto rtattr_failure; 733 goto nla_put_failure;
731 734
732#ifdef CONFIG_NET_CLS_IND 735#ifdef CONFIG_NET_CLS_IND
733 if(strlen(n->indev)) 736 if(strlen(n->indev))
734 RTA_PUT(skb, TCA_U32_INDEV, IFNAMSIZ, n->indev); 737 NLA_PUT_STRING(skb, TCA_U32_INDEV, n->indev);
735#endif 738#endif
736#ifdef CONFIG_CLS_U32_PERF 739#ifdef CONFIG_CLS_U32_PERF
737 RTA_PUT(skb, TCA_U32_PCNT, 740 NLA_PUT(skb, TCA_U32_PCNT,
738 sizeof(struct tc_u32_pcnt) + n->sel.nkeys*sizeof(u64), 741 sizeof(struct tc_u32_pcnt) + n->sel.nkeys*sizeof(u64),
739 n->pf); 742 n->pf);
740#endif 743#endif
741 } 744 }
742 745
743 rta->rta_len = skb_tail_pointer(skb) - b; 746 nla_nest_end(skb, nest);
747
744 if (TC_U32_KEY(n->handle)) 748 if (TC_U32_KEY(n->handle))
745 if (tcf_exts_dump_stats(skb, &n->exts, &u32_ext_map) < 0) 749 if (tcf_exts_dump_stats(skb, &n->exts, &u32_ext_map) < 0)
746 goto rtattr_failure; 750 goto nla_put_failure;
747 return skb->len; 751 return skb->len;
748 752
749rtattr_failure: 753nla_put_failure:
750 nlmsg_trim(skb, b); 754 nla_nest_cancel(skb, nest);
751 return -1; 755 return -1;
752} 756}
753 757
754static struct tcf_proto_ops cls_u32_ops = { 758static struct tcf_proto_ops cls_u32_ops __read_mostly = {
755 .next = NULL,
756 .kind = "u32", 759 .kind = "u32",
757 .classify = u32_classify, 760 .classify = u32_classify,
758 .init = u32_init, 761 .init = u32_init,