Here is the lastest version of the netem patch to use hrtimers.
It is against the current net tree, so it will need adjusting to fit
with new psched/ktime stuff.

---
 include/net/pkt_sched.h |    3 ++
 net/sched/sch_api.c     |   30 +++++++++++++++++++++
 net/sched/sch_netem.c   |   68 ++++++++++++++++++++++++------------------------
 3 files changed, 67 insertions(+), 34 deletions(-)

--- netem-dev.orig/net/sched/sch_netem.c
+++ netem-dev/net/sched/sch_netem.c
@@ -54,7 +54,7 @@
 
 struct netem_sched_data {
        struct Qdisc    *qdisc;
-       struct timer_list timer;
+       struct hrtimer   timer;
 
        u32 latency;
        u32 loss;
@@ -78,8 +78,9 @@ struct netem_sched_data {
 };
 
 /* Time stamp put into socket buffer control block */
+/* TODO: move this to skb->timestamp */
 struct netem_skb_cb {
-       psched_time_t   time_to_send;
+       ktime_t due_time;
 };
 
 /* init_crandom - initialize correlated random number generator
@@ -207,14 +208,14 @@ static int netem_enqueue(struct sk_buff 
        if (q->gap == 0                 /* not doing reordering */
            || q->counter < q->gap      /* inside last reordering gap */
            || q->reorder < get_crandom(&q->reorder_cor)) {
-               psched_time_t now;
-               psched_tdiff_t delay;
+               u64 ns;
 
-               delay = tabledist(q->latency, q->jitter,
-                                 &q->delay_cor, q->delay_dist);
+               ns = tabledist(q->latency, q->jitter,
+                              &q->delay_cor, q->delay_dist) * 1000ul;
+
+
+               cb->due_time = ktime_add_ns(ktime_get(), ns);
 
-               PSCHED_GET_TIME(now);
-               PSCHED_TADD2(now, delay, cb->time_to_send);
                ++q->counter;
                ret = q->qdisc->enqueue(skb, q->qdisc);
        } else {
@@ -222,7 +223,7 @@ static int netem_enqueue(struct sk_buff 
                 * Do re-ordering by putting one out of N packets at the front
                 * of the queue.
                 */
-               PSCHED_GET_TIME(cb->time_to_send);
+               cb->due_time = ktime_get();
                q->counter = 0;
                ret = q->qdisc->ops->requeue(skb, q->qdisc);
        }
@@ -273,41 +274,40 @@ static struct sk_buff *netem_dequeue(str
        if (skb) {
                const struct netem_skb_cb *cb
                        = (const struct netem_skb_cb *)skb->cb;
-               psched_time_t now;
+               ktime_t now = ktime_get();
 
-               /* if more time remaining? */
-               PSCHED_GET_TIME(now);
-
-               if (PSCHED_TLESS(cb->time_to_send, now)) {
+               /* if time has come to send? */
+               if (now.tv64 <= cb->due_time.tv64) {
                        pr_debug("netem_dequeue: return skb=%p\n", skb);
                        sch->q.qlen--;
                        sch->flags &= ~TCQ_F_THROTTLED;
                        return skb;
-               } else {
-                       psched_tdiff_t delay = PSCHED_TDIFF(cb->time_to_send, 
now);
-
-                       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);
-                       }
+               }
 
-                       mod_timer(&q->timer, jiffies + PSCHED_US2JIFFIE(delay));
-                       sch->flags |= TCQ_F_THROTTLED;
+               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);
                }
+
+               hrtimer_start(&q->timer, cb->due_time, HRTIMER_MODE_ABS);
+               sch->flags |= TCQ_F_THROTTLED;
        }
 
        return NULL;
 }
 
-static void netem_watchdog(unsigned long arg)
+static enum hrtimer_restart netem_watchdog(struct hrtimer *hrt)
 {
-       struct Qdisc *sch = (struct Qdisc *)arg;
+       struct netem_sched_data *q
+               = container_of(hrt, struct netem_sched_data, timer);
+       struct Qdisc *sch = q->qdisc;
 
        pr_debug("netem_watchdog qlen=%d\n", sch->q.qlen);
        sch->flags &= ~TCQ_F_THROTTLED;
        netif_schedule(sch->dev);
+       return HRTIMER_NORESTART;
 }
 
 static void netem_reset(struct Qdisc *sch)
@@ -317,7 +317,7 @@ static void netem_reset(struct Qdisc *sc
        qdisc_reset(q->qdisc);
        sch->q.qlen = 0;
        sch->flags &= ~TCQ_F_THROTTLED;
-       del_timer_sync(&q->timer);
+       hrtimer_cancel(&q->timer);
 }
 
 /* Pass size change message down to embedded FIFO */
@@ -502,7 +502,8 @@ static int tfifo_enqueue(struct sk_buff 
                        const struct netem_skb_cb *cb
                                = (const struct netem_skb_cb *)skb->cb;
 
-                       if (!PSCHED_TLESS(ncb->time_to_send, cb->time_to_send))
+                       if (ktime_to_ns(ktime_sub(ncb->due_time,
+                                                 cb->due_time)) >= 0)
                                break;
                }
 
@@ -567,9 +568,8 @@ static int netem_init(struct Qdisc *sch,
        if (!opt)
                return -EINVAL;
 
-       init_timer(&q->timer);
+       hrtimer_init(&q->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
        q->timer.function = netem_watchdog;
-       q->timer.data = (unsigned long) sch;
 
        q->qdisc = qdisc_create_dflt(sch->dev, &tfifo_qdisc_ops,
                                     TC_H_MAKE(sch->handle, 1));
@@ -590,7 +590,7 @@ static void netem_destroy(struct Qdisc *
 {
        struct netem_sched_data *q = qdisc_priv(sch);
 
-       del_timer_sync(&q->timer);
+       hrtimer_cancel(&q->timer);
        qdisc_destroy(q->qdisc);
        kfree(q->delay_dist);
 }
@@ -605,8 +605,8 @@ static int netem_dump(struct Qdisc *sch,
        struct tc_netem_reorder reorder;
        struct tc_netem_corrupt corrupt;
 
-       qopt.latency = q->latency;
-       qopt.jitter = q->jitter;
+       qopt.latency = psched_usecs2ticks(q->latency);
+       qopt.jitter = psched_usecs2ticks(q->jitter);
        qopt.limit = q->limit;
        qopt.loss = q->loss;
        qopt.gap = q->gap;
--- netem-dev.orig/include/net/pkt_sched.h
+++ netem-dev/include/net/pkt_sched.h
@@ -239,4 +239,7 @@ static inline unsigned psched_mtu(struct
        return dev->hard_header ? mtu + dev->hard_header_len : mtu;
 }
 
+extern unsigned long psched_usecs2ticks(unsigned long us);
+extern unsigned long psched_ticks2usecs(unsigned long ticks);
+
 #endif
--- netem-dev.orig/net/sched/sch_api.c
+++ netem-dev/net/sched/sch_api.c
@@ -1178,6 +1178,36 @@ reclassify:
 static int psched_us_per_tick = 1;
 static int psched_tick_per_us = 1;
 
+
+/**
+ * psched_ticks2usecs - convert from scaled PSCHED ticks to usecs
+ * @ticks: pscehed ticks
+ * Returns time in microseconds
+ */
+unsigned long psched_ticks2usecs(unsigned long ticks)
+{
+       u64 t = ticks;
+
+       t *= psched_us_per_tick;
+       do_div(t, psched_tick_per_us);
+       return t;
+}
+EXPORT_SYMBOL(psched_ticks2usecs);
+
+/**
+ * psched_usecs2ticks - convert from usecs to PSCHED ticks
+ * @us: time in microseconds
+ */
+unsigned long psched_usecs2ticks(unsigned long us)
+{
+       u64 t = us;
+
+       t *= psched_tick_per_us;
+       do_div(t, psched_us_per_tick);
+       return t;
+}
+EXPORT_SYMBOL(psched_usecs2ticks);
+
 #ifdef CONFIG_PROC_FS
 static int psched_show(struct seq_file *seq, void *v)
 {
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to