Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / net / sched / sch_prio.c
index 6961f08..3395ca7 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/module.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -47,36 +47,23 @@ struct prio_sched_data
 };
 
 
-struct Qdisc *prio_classify(struct sk_buff *skb, struct Qdisc *sch,int *r)
+static struct Qdisc *
+prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
 {
        struct prio_sched_data *q = qdisc_priv(sch);
        u32 band = skb->priority;
        struct tcf_result res;
 
+       *qerr = NET_XMIT_BYPASS;
        if (TC_H_MAJ(skb->priority) != sch->handle) {
 #ifdef CONFIG_NET_CLS_ACT
-               int result = 0, terminal = 0;
-               result = tc_classify(skb, q->filter_list, &res);
-
-               switch (result) {
-                       case TC_ACT_SHOT:
-                               *r = NET_XMIT_DROP;
-                               terminal = 1;
-                               break;
-                       case TC_ACT_STOLEN:
-                       case TC_ACT_QUEUED:
-                               terminal = 1;
-                               break;
-                       case TC_ACT_RECLASSIFY:
-                       case TC_ACT_OK:
-                       case TC_ACT_UNSPEC:
-                       default:
-                       break;
-               };
-               if (terminal) {
-                       kfree_skb(skb);
+               switch (tc_classify(skb, q->filter_list, &res)) {
+               case TC_ACT_STOLEN:
+               case TC_ACT_QUEUED:
+                       *qerr = NET_XMIT_SUCCESS;
+               case TC_ACT_SHOT:
                        return NULL;
-               } 
+               };
 
                if (!q->filter_list ) {
 #else
@@ -96,33 +83,29 @@ struct Qdisc *prio_classify(struct sk_buff *skb, struct Qdisc *sch,int *r)
 }
 
 static int
-prio_enqueue(struct sk_buff *skb, struct Qdiscsch)
+prio_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 {
        struct Qdisc *qdisc;
-       int ret = NET_XMIT_SUCCESS;
+       int ret;
 
        qdisc = prio_classify(skb, sch, &ret);
+#ifdef CONFIG_NET_CLS_ACT
+       if (qdisc == NULL) {
 
-       if (NULL == qdisc)
-               goto dropped;
+               if (ret == NET_XMIT_BYPASS)
+                       sch->qstats.drops++;
+               kfree_skb(skb);
+               return ret;
+       }
+#endif
 
        if ((ret = qdisc->enqueue(skb, qdisc)) == NET_XMIT_SUCCESS) {
-               sch->stats.bytes += skb->len;
-               sch->stats.packets++;
+               sch->bstats.bytes += skb->len;
+               sch->bstats.packets++;
                sch->q.qlen++;
                return NET_XMIT_SUCCESS;
        }
-
-dropped:
-#ifdef CONFIG_NET_CLS_ACT
-       if (NET_XMIT_DROP == ret) {
-#endif
-               sch->stats.drops++;
-#ifdef CONFIG_NET_CLS_ACT
-       } else {
-               sch->stats.overlimits++; /* abuse, but noone uses it */
-       }
-#endif
+       sch->qstats.drops++;
        return ret; 
 }
 
@@ -131,18 +114,24 @@ static int
 prio_requeue(struct sk_buff *skb, struct Qdisc* sch)
 {
        struct Qdisc *qdisc;
-       int ret = NET_XMIT_DROP;
+       int ret;
 
        qdisc = prio_classify(skb, sch, &ret);
-       if (qdisc == NULL)
-               goto dropped;
+#ifdef CONFIG_NET_CLS_ACT
+       if (qdisc == NULL) {
+               if (ret == NET_XMIT_BYPASS)
+                       sch->qstats.drops++;
+               kfree_skb(skb);
+               return ret;
+       }
+#endif
 
-       if ((ret = qdisc->ops->requeue(skb, qdisc)) == 0) {
+       if ((ret = qdisc->ops->requeue(skb, qdisc)) == NET_XMIT_SUCCESS) {
                sch->q.qlen++;
+               sch->qstats.requeues++;
                return 0;
        }
-dropped:
-       sch->stats.drops++;
+       sch->qstats.drops++;
        return NET_XMIT_DROP;
 }
 
@@ -176,7 +165,7 @@ static unsigned int prio_drop(struct Qdisc* sch)
 
        for (prio = q->bands-1; prio >= 0; prio--) {
                qdisc = q->queues[prio];
-               if ((len = qdisc->ops->drop(qdisc)) != 0) {
+               if (qdisc->ops->drop && (len = qdisc->ops->drop(qdisc)) != 0) {
                        sch->q.qlen--;
                        return len;
                }
@@ -239,14 +228,13 @@ static int prio_tune(struct Qdisc *sch, struct rtattr *opt)
        }
        sch_tree_unlock(sch);
 
-       for (i=0; i<=TC_PRIO_MAX; i++) {
-               int band = q->prio2band[i];
-               if (q->queues[band] == &noop_qdisc) {
+       for (i=0; i<q->bands; i++) {
+               if (q->queues[i] == &noop_qdisc) {
                        struct Qdisc *child;
                        child = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
                        if (child) {
                                sch_tree_lock(sch);
-                               child = xchg(&q->queues[band], child);
+                               child = xchg(&q->queues[i], child);
 
                                if (child != &noop_qdisc)
                                        qdisc_destroy(child);