]> err.no Git - linux-2.6/blobdiff - net/sched/sch_netem.c
Merge branch 'for-2.6.24' of master.kernel.org:/pub/scm/linux/kernel/git/galak/powerp...
[linux-2.6] / net / sched / sch_netem.c
index 7e9e658d4d93dd6c0d1270c6b25222e8f00234ef..9e5e87e81f002433cf6cac0ea4ac3f8db519b3fc 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 
@@ -102,7 +100,7 @@ static u32 get_crandom(struct crndstate *state)
        u64 value, rho;
        unsigned long answer;
 
-       if (state->rho == 0)    /* no correllation */
+       if (state->rho == 0)    /* no correlation */
                return net_random();
 
        value = net_random();
@@ -217,8 +215,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                delay = tabledist(q->latency, q->jitter,
                                  &q->delay_cor, q->delay_dist);
 
-               PSCHED_GET_TIME(now);
-               PSCHED_TADD2(now, delay, cb->time_to_send);
+               now = psched_get_time();
+               cb->time_to_send = now + delay;
                ++q->counter;
                ret = q->qdisc->enqueue(skb, q->qdisc);
        } else {
@@ -226,7 +224,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                 * Do re-ordering by putting one out of N packets at the front
                 * of the queue.
                 */
-               PSCHED_GET_TIME(cb->time_to_send);
+               cb->time_to_send = psched_get_time();
                q->counter = 0;
                ret = q->qdisc->ops->requeue(skb, q->qdisc);
        }
@@ -273,30 +271,31 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
        struct netem_sched_data *q = qdisc_priv(sch);
        struct sk_buff *skb;
 
+       smp_mb();
+       if (sch->flags & TCQ_F_THROTTLED)
+               return NULL;
+
        skb = q->qdisc->dequeue(q->qdisc);
        if (skb) {
                const struct netem_skb_cb *cb
                        = (const struct netem_skb_cb *)skb->cb;
-               psched_time_t now;
+               psched_time_t now = psched_get_time();
 
                /* if more time remaining? */
-               PSCHED_GET_TIME(now);
-
-               if (PSCHED_TLESS(cb->time_to_send, now)) {
+               if (cb->time_to_send <= now) {
                        pr_debug("netem_dequeue: return skb=%p\n", skb);
                        sch->q.qlen--;
-                       sch->flags &= ~TCQ_F_THROTTLED;
                        return skb;
-               } else {
-                       qdisc_watchdog_schedule(&q->watchdog, cb->time_to_send);
-
-                       if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) {
-                               qdisc_tree_decrease_qlen(q->qdisc, 1);
-                               sch->qstats.drops++;
-                               printk(KERN_ERR "netem: queue discpline %s could not requeue\n",
-                                      q->qdisc->ops->id);
-                       }
                }
+
+               if (unlikely(q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS)) {
+                       qdisc_tree_decrease_qlen(q->qdisc, 1);
+                       sch->qstats.drops++;
+                       printk(KERN_ERR "netem: %s could not requeue\n",
+                              q->qdisc->ops->id);
+               }
+
+               qdisc_watchdog_schedule(&q->watchdog, cb->time_to_send);
        }
 
        return NULL;
@@ -429,8 +428,8 @@ static int netem_change(struct Qdisc *sch, struct rtattr *opt)
        q->loss = qopt->loss;
        q->duplicate = qopt->duplicate;
 
-       /* for compatiablity with earlier versions.
-        * if gap is set, need to assume 100% probablity
+       /* for compatibility with earlier versions.
+        * if gap is set, need to assume 100% probability
         */
        if (q->gap)
                q->reorder = ~0;
@@ -491,7 +490,7 @@ static int tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
 
        if (likely(skb_queue_len(list) < q->limit)) {
                /* Optimize for add at tail */
-               if (likely(skb_queue_empty(list) || !PSCHED_TLESS(tnext, q->oldest))) {
+               if (likely(skb_queue_empty(list) || tnext >= q->oldest)) {
                        q->oldest = tnext;
                        return qdisc_enqueue_tail(nskb, sch);
                }
@@ -500,7 +499,7 @@ static int tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
                        const struct netem_skb_cb *cb
                                = (const struct netem_skb_cb *)skb->cb;
 
-                       if (!PSCHED_TLESS(tnext, cb->time_to_send))
+                       if (tnext >= cb->time_to_send)
                                break;
                }
 
@@ -529,7 +528,7 @@ static int tfifo_init(struct Qdisc *sch, struct rtattr *opt)
        } else
                q->limit = max_t(u32, sch->dev->tx_queue_len, 1);
 
-       PSCHED_SET_PASTPERFECT(q->oldest);
+       q->oldest = PSCHED_PASTPERFECT;
        return 0;
 }