This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / net / sched / sch_api.c
index fff96b7..59d8313 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/seq_file.h>
 #include <linux/kmod.h>
 #include <linux/list.h>
-#include <linux/bitops.h>
 
 #include <net/sock.h>
 #include <net/pkt_sched.h>
@@ -43,6 +42,7 @@
 #include <asm/processor.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
+#include <asm/bitops.h>
 
 static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, u32 clid,
                        struct Qdisc *old, struct Qdisc *new);
@@ -196,14 +196,10 @@ struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
 {
        struct Qdisc *q;
 
-       read_lock_bh(&qdisc_tree_lock);
        list_for_each_entry(q, &dev->qdisc_list, list) {
-               if (q->handle == handle) {
-                       read_unlock_bh(&qdisc_tree_lock);
+               if (q->handle == handle)
                        return q;
-               }
        }
-       read_unlock_bh(&qdisc_tree_lock);
        return NULL;
 }
 
@@ -233,11 +229,8 @@ struct Qdisc_ops *qdisc_lookup_ops(struct rtattr *kind)
        if (kind) {
                read_lock(&qdisc_mod_lock);
                for (q = qdisc_base; q; q = q->next) {
-                       if (rtattr_strcmp(kind, q->id) == 0) {
-                               if (!try_module_get(q->owner))
-                                       q = NULL;
+                       if (rtattr_strcmp(kind, q->id) == 0)
                                break;
-                       }
                }
                read_unlock(&qdisc_mod_lock);
        }
@@ -315,7 +308,7 @@ dev_graft_qdisc(struct net_device *dev, struct Qdisc *qdisc)
                dev_deactivate(dev);
 
        qdisc_lock_tree(dev);
-       if (qdisc && qdisc->flags&TCQ_F_INGRESS) {
+       if (qdisc && qdisc->flags&TCQ_F_INGRES) {
                oqdisc = dev->qdisc_ingress;
                /* Prune old scheduler */
                if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1) {
@@ -364,7 +357,7 @@ int qdisc_graft(struct net_device *dev, struct Qdisc *parent, u32 classid,
 
 
        if (parent == NULL) { 
-               if (q && q->flags&TCQ_F_INGRESS) {
+               if (q && q->flags&TCQ_F_INGRES) {
                        *old = dev_graft_qdisc(dev, q);
                } else {
                        *old = dev_graft_qdisc(dev, new);
@@ -416,6 +409,9 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
        err = -EINVAL;
        if (ops == NULL)
                goto err_out;
+       err = -EBUSY;
+       if (!try_module_get(ops->owner))
+               goto err_out;
 
        /* ensure that the Qdisc and the private data are 32-byte aligned */
        size = ((sizeof(*sch) + QDISC_ALIGN_CONST) & ~QDISC_ALIGN_CONST);
@@ -434,7 +430,7 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
        skb_queue_head_init(&sch->q);
 
        if (handle == TC_H_INGRESS)
-               sch->flags |= TCQ_F_INGRESS;
+               sch->flags |= TCQ_F_INGRES;
 
        sch->ops = ops;
        sch->enqueue = ops->enqueue;
@@ -455,6 +451,9 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
         else
                 sch->handle = handle;
 
+       /* enqueue is accessed locklessly - make sure it's visible
+        * before we set a netdevice's qdisc pointer to sch */
+       smp_wmb();
        if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) {
                qdisc_lock_tree(dev);
                list_add_tail(&sch->list, &dev->qdisc_list);
@@ -462,8 +461,8 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
 
 #ifdef CONFIG_NET_ESTIMATOR
                if (tca[TCA_RATE-1])
-                       gen_new_estimator(&sch->bstats, &sch->rate_est,
-                               sch->stats_lock, tca[TCA_RATE-1]);
+                       qdisc_new_estimator(&sch->stats, sch->stats_lock,
+                                           tca[TCA_RATE-1]);
 #endif
                return sch;
        }
@@ -490,9 +489,11 @@ static int qdisc_change(struct Qdisc *sch, struct rtattr **tca)
                        return err;
        }
 #ifdef CONFIG_NET_ESTIMATOR
-       if (tca[TCA_RATE-1])
-               gen_replace_estimator(&sch->bstats, &sch->rate_est,
-                       sch->stats_lock, tca[TCA_RATE-1]);
+       if (tca[TCA_RATE-1]) {
+               qdisc_kill_estimator(&sch->stats);
+               qdisc_new_estimator(&sch->stats, sch->stats_lock,
+                                   tca[TCA_RATE-1]);
+       }
 #endif
        return 0;
 }
@@ -730,13 +731,25 @@ graft:
        return 0;
 }
 
+int qdisc_copy_stats(struct sk_buff *skb, struct tc_stats *st, spinlock_t *lock)
+{
+       spin_lock_bh(lock);
+       RTA_PUT(skb, TCA_STATS, sizeof(struct tc_stats), st);
+       spin_unlock_bh(lock);
+       return 0;
+
+rtattr_failure:
+       spin_unlock_bh(lock);
+       return -1;
+}
+
+
 static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
                         u32 pid, u32 seq, unsigned flags, int event)
 {
        struct tcmsg *tcm;
        struct nlmsghdr  *nlh;
        unsigned char    *b = skb->tail;
-       struct gnet_dump d;
 
        nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*tcm));
        nlh->nlmsg_flags = flags;
@@ -749,25 +762,9 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
        RTA_PUT(skb, TCA_KIND, IFNAMSIZ, q->ops->id);
        if (q->ops->dump && q->ops->dump(q, skb) < 0)
                goto rtattr_failure;
-       q->qstats.qlen = q->q.qlen;
-
-       if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
-                       TCA_XSTATS, q->stats_lock, &d) < 0)
-               goto rtattr_failure;
-
-       if (q->ops->dump_stats && q->ops->dump_stats(q, &d) < 0)
-               goto rtattr_failure;
-
-       if (gnet_stats_copy_basic(&d, &q->bstats) < 0 ||
-#ifdef CONFIG_NET_ESTIMATOR
-           gnet_stats_copy_rate_est(&d, &q->rate_est) < 0 ||
-#endif
-           gnet_stats_copy_queue(&d, &q->qstats) < 0)
-               goto rtattr_failure;
-       
-       if (gnet_stats_finish_copy(&d) < 0)
+       q->stats.qlen = q->q.qlen;
+       if (qdisc_copy_stats(skb, &q->stats, q->stats_lock))
                goto rtattr_failure;
-       
        nlh->nlmsg_len = skb->tail - b;
        return skb->len;
 
@@ -973,8 +970,6 @@ static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q,
        struct tcmsg *tcm;
        struct nlmsghdr  *nlh;
        unsigned char    *b = skb->tail;
-       struct gnet_dump d;
-       struct Qdisc_class_ops *cl_ops = q->ops->cl_ops;
 
        nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*tcm));
        nlh->nlmsg_flags = flags;
@@ -985,19 +980,8 @@ static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q,
        tcm->tcm_handle = q->handle;
        tcm->tcm_info = 0;
        RTA_PUT(skb, TCA_KIND, IFNAMSIZ, q->ops->id);
-       if (cl_ops->dump && cl_ops->dump(q, cl, skb, tcm) < 0)
+       if (q->ops->cl_ops->dump && q->ops->cl_ops->dump(q, cl, skb, tcm) < 0)
                goto rtattr_failure;
-
-       if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
-                       TCA_XSTATS, q->stats_lock, &d) < 0)
-               goto rtattr_failure;
-
-       if (cl_ops->dump_stats && cl_ops->dump_stats(q, cl, &d) < 0)
-               goto rtattr_failure;
-
-       if (gnet_stats_finish_copy(&d) < 0)
-               goto rtattr_failure;
-
        nlh->nlmsg_len = skb->tail - b;
        return skb->len;
 
@@ -1087,54 +1071,8 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
        return skb->len;
 }
 
-/* Main classifier routine: scans classifier chain attached
-   to this qdisc, (optionally) tests for protocol and asks
-   specific classifiers.
- */
-int tc_classify(struct sk_buff *skb, struct tcf_proto *tp,
-       struct tcf_result *res)
-{
-       int err = 0;
-       u32 protocol = skb->protocol;
-#ifdef CONFIG_NET_CLS_ACT
-       struct tcf_proto *otp = tp;
-reclassify:
-#endif
-       protocol = skb->protocol;
-
-       for ( ; tp; tp = tp->next) {
-               if ((tp->protocol == protocol ||
-                       tp->protocol == __constant_htons(ETH_P_ALL)) &&
-                       (err = tp->classify(skb, tp, res)) >= 0) {
-#ifdef CONFIG_NET_CLS_ACT
-                       if ( TC_ACT_RECLASSIFY == err) {
-                               __u32 verd = (__u32) G_TC_VERD(skb->tc_verd);
-                               tp = otp;
-
-                               if (MAX_REC_LOOP < verd++) {
-                                       printk("rule prio %d protocol %02x reclassify is buggy packet dropped\n",
-                                               tp->prio&0xffff, ntohs(tp->protocol));
-                                       return TC_ACT_SHOT;
-                               }
-                               skb->tc_verd = SET_TC_VERD(skb->tc_verd,verd);
-                               goto reclassify;
-                       } else {
-                               if (skb->tc_verd) 
-                                       skb->tc_verd = SET_TC_VERD(skb->tc_verd,0);
-                               return err;
-                       }
-#else
-
-                       return err;
-#endif
-               }
-
-       }
-       return -1;
-}
-
-static int psched_us_per_tick = 1;
-static int psched_tick_per_us = 1;
+int psched_us_per_tick = 1;
+int psched_tick_per_us = 1;
 
 #ifdef CONFIG_PROC_FS
 static int psched_show(struct seq_file *seq, void *v)
@@ -1260,8 +1198,8 @@ static int __init pktsched_init(void)
 
 subsys_initcall(pktsched_init);
 
+EXPORT_SYMBOL(qdisc_copy_stats);
 EXPORT_SYMBOL(qdisc_get_rtab);
 EXPORT_SYMBOL(qdisc_put_rtab);
 EXPORT_SYMBOL(register_qdisc);
 EXPORT_SYMBOL(unregister_qdisc);
-EXPORT_SYMBOL(tc_classify);