missing bits of net-namespace / sysctl
[safe/jmp/linux-2.6] / net / sched / sch_red.c
index 6ce8da5..3f2d1d7 100644 (file)
@@ -92,9 +92,9 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch)
                        break;
        }
 
-       ret = child->enqueue(skb, child);
+       ret = qdisc_enqueue(skb, child);
        if (likely(ret == NET_XMIT_SUCCESS)) {
-               sch->bstats.bytes += skb->len;
+               sch->bstats.bytes += qdisc_pkt_len(skb);
                sch->bstats.packets++;
                sch->q.qlen++;
        } else {
@@ -174,32 +174,10 @@ static void red_destroy(struct Qdisc *sch)
        qdisc_destroy(q->qdisc);
 }
 
-static struct Qdisc *red_create_dflt(struct Qdisc *sch, u32 limit)
-{
-       struct Qdisc *q;
-       struct nlattr *nla;
-       int ret;
-
-       q = qdisc_create_dflt(sch->dev, &bfifo_qdisc_ops,
-                             TC_H_MAKE(sch->handle, 1));
-       if (q) {
-               nla = kmalloc(nla_attr_size(sizeof(struct tc_fifo_qopt)),
-                             GFP_KERNEL);
-               if (nla) {
-                       nla->nla_type = RTM_NEWQDISC;
-                       nla->nla_len = nla_attr_size(sizeof(struct tc_fifo_qopt));
-                       ((struct tc_fifo_qopt *)nla_data(nla))->limit = limit;
-
-                       ret = q->ops->change(q, nla);
-                       kfree(nla);
-
-                       if (ret == 0)
-                               return q;
-               }
-               qdisc_destroy(q);
-       }
-       return NULL;
-}
+static const struct nla_policy red_policy[TCA_RED_MAX + 1] = {
+       [TCA_RED_PARMS] = { .len = sizeof(struct tc_red_qopt) },
+       [TCA_RED_STAB]  = { .len = RED_STAB_SIZE },
+};
 
 static int red_change(struct Qdisc *sch, struct nlattr *opt)
 {
@@ -207,22 +185,25 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt)
        struct nlattr *tb[TCA_RED_MAX + 1];
        struct tc_red_qopt *ctl;
        struct Qdisc *child = NULL;
+       int err;
 
-       if (opt == NULL || nla_parse_nested(tb, TCA_RED_MAX, opt, NULL))
+       if (opt == NULL)
                return -EINVAL;
 
+       err = nla_parse_nested(tb, TCA_RED_MAX, opt, red_policy);
+       if (err < 0)
+               return err;
+
        if (tb[TCA_RED_PARMS] == NULL ||
-           nla_len(tb[TCA_RED_PARMS]) < sizeof(*ctl) ||
-           tb[TCA_RED_STAB] == NULL ||
-           nla_len(tb[TCA_RED_STAB]) < RED_STAB_SIZE)
+           tb[TCA_RED_STAB] == NULL)
                return -EINVAL;
 
        ctl = nla_data(tb[TCA_RED_PARMS]);
 
        if (ctl->limit > 0) {
-               child = red_create_dflt(sch, ctl->limit);
-               if (child == NULL)
-                       return -ENOMEM;
+               child = fifo_create_dflt(sch, &bfifo_qdisc_ops, ctl->limit);
+               if (IS_ERR(child))
+                       return PTR_ERR(child);
        }
 
        sch_tree_lock(sch);
@@ -273,7 +254,8 @@ static int red_dump(struct Qdisc *sch, struct sk_buff *skb)
        return nla_nest_end(skb, opts);
 
 nla_put_failure:
-       return nla_nest_cancel(skb, opts);
+       nla_nest_cancel(skb, opts);
+       return -EMSGSIZE;
 }
 
 static int red_dump_stats(struct Qdisc *sch, struct gnet_dump *d)