net-sched: consolidate default fifo qdisc setup
Patrick McHardy [Sun, 6 Jul 2008 06:40:21 +0000 (23:40 -0700)]
Signed-off-by: Patrick McHardy <kaber@trash.net>
Acked-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

include/net/pkt_sched.h
net/sched/sch_fifo.c
net/sched/sch_netem.c
net/sched/sch_red.c
net/sched/sch_tbf.c

index 46fb4d8..8e3a0c4 100644 (file)
@@ -72,6 +72,10 @@ extern void qdisc_watchdog_cancel(struct qdisc_watchdog *wd);
 extern struct Qdisc_ops pfifo_qdisc_ops;
 extern struct Qdisc_ops bfifo_qdisc_ops;
 
+extern int fifo_set_limit(struct Qdisc *q, unsigned int limit);
+extern struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops,
+                                     unsigned int limit);
+
 extern int register_qdisc(struct Qdisc_ops *qops);
 extern int unregister_qdisc(struct Qdisc_ops *qops);
 extern struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle);
index 95ed482..82d7d7b 100644 (file)
@@ -107,3 +107,45 @@ struct Qdisc_ops bfifo_qdisc_ops __read_mostly = {
        .owner          =       THIS_MODULE,
 };
 EXPORT_SYMBOL(bfifo_qdisc_ops);
+
+/* Pass size change message down to embedded FIFO */
+int fifo_set_limit(struct Qdisc *q, unsigned int limit)
+{
+       struct nlattr *nla;
+       int ret = -ENOMEM;
+
+       /* Hack to avoid sending change message to non-FIFO */
+       if (strncmp(q->ops->id + 1, "fifo", 4) != 0)
+               return 0;
+
+       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);
+       }
+       return ret;
+}
+EXPORT_SYMBOL(fifo_set_limit);
+
+struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops,
+                              unsigned int limit)
+{
+       struct Qdisc *q;
+       int err = -ENOMEM;
+
+       q = qdisc_create_dflt(sch->dev, ops, TC_H_MAKE(sch->handle, 1));
+       if (q) {
+               err = fifo_set_limit(q, limit);
+               if (err < 0) {
+                       qdisc_destroy(q);
+                       q = NULL;
+               }
+       }
+
+       return q ? : ERR_PTR(err);
+}
+EXPORT_SYMBOL(fifo_create_dflt);
index c9c649b..2469766 100644 (file)
@@ -310,28 +310,6 @@ static void netem_reset(struct Qdisc *sch)
        qdisc_watchdog_cancel(&q->watchdog);
 }
 
-/* Pass size change message down to embedded FIFO */
-static int set_fifo_limit(struct Qdisc *q, int limit)
-{
-       struct nlattr *nla;
-       int ret = -ENOMEM;
-
-       /* Hack to avoid sending change message to non-FIFO */
-       if (strncmp(q->ops->id + 1, "fifo", 4) != 0)
-               return 0;
-
-       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);
-       }
-       return ret;
-}
-
 /*
  * Distribution data is a variable size payload containing
  * signed 16 bit values.
@@ -416,7 +394,7 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt)
        if (ret < 0)
                return ret;
 
-       ret = set_fifo_limit(q->qdisc, qopt->limit);
+       ret = fifo_set_limit(q->qdisc, qopt->limit);
        if (ret) {
                pr_debug("netem: can't set fifo limit\n");
                return ret;
index 5c56985..77098ac 100644 (file)
@@ -174,33 +174,6 @@ 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 },
@@ -228,9 +201,9 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt)
        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);
index 0b7d78f..444c227 100644 (file)
@@ -242,34 +242,6 @@ static void tbf_reset(struct Qdisc* sch)
        qdisc_watchdog_cancel(&q->watchdog);
 }
 
-static struct Qdisc *tbf_create_dflt_qdisc(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 tbf_policy[TCA_TBF_MAX + 1] = {
        [TCA_TBF_PARMS] = { .len = sizeof(struct tc_tbf_qopt) },
        [TCA_TBF_RTAB]  = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
@@ -322,8 +294,11 @@ static int tbf_change(struct Qdisc* sch, struct nlattr *opt)
                goto done;
 
        if (qopt->limit > 0) {
-               if ((child = tbf_create_dflt_qdisc(sch, qopt->limit)) == NULL)
+               child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit);
+               if (IS_ERR(child)) {
+                       err = PTR_ERR(child);
                        goto done;
+               }
        }
 
        sch_tree_lock(sch);