netdev
[Top] [All Lists]

Re: [Netem] [PATCH] netem: change packet scheduling

To: "Stephen Hemminger" <shemminger@xxxxxxxx>
Subject: Re: [Netem] [PATCH] netem: change packet scheduling
From: "Julio Kriger" <jkriger@xxxxxxxxxxx>
Date: Sat, 16 Apr 2005 12:30:28 -0300 (ART)
Cc: "David S. Miller" <davem@xxxxxxxxxxxxx>, netdev@xxxxxxxxxxx, netem@xxxxxxxxxxxxxx
Importance: Normal
In-reply-to: <20050412143541.260fdff4@dxpl.pdx.osdl.net>
References: <20050412143541.260fdff4@dxpl.pdx.osdl.net>
Reply-to: jkriger@xxxxxxxxxx
Sender: netdev-bounce@xxxxxxxxxxx
User-agent: SquirrelMail/1.4.3a
Hi!
I've installed linux-2.6.11-r5 on my PC and I couldn't apply the patch. I
get:

julio root # patch -p1  --dry-run < patch_netem.patch
missing header for unified diff at line 3 of patch
can't find file to patch at input line 3
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|--- sch_netem.c        2005-04-04 09:39:41.000000000 -0700
|+++ sch_netem.c        2005-04-06 15:54:09.514780384 -0700
--------------------------
File to patch: n/sch_netem.c
patching file n/sch_netem.c
patch: **** malformed patch at line 5:

('n' is a softlink to /usr/src/linux/net/sched)

From what I read, this patch is to apply to a linux-2.6.12-rc2. Could you
change it so I could apply it to a linux-2.6.11-r5, please? TIA.

Regards,

Julio

-- 
-------------------------------
Julio Kriger
jkriger AT hotpop DOT com
jkriger AT cwazy DOT co DOT uk

<quote who="Stephen Hemminger">
> Netem was dumping packets into the child qdisc when timer expires.
> This creates problems if netem is not the root qdisc and can even cause
> a livelock situation. This patch changes it to only transfer packets
> during
> the enqueue/dequeue routines.
>
> This alternative makes netem be self clocking as well, so if using the CPU
> counter for the timing source it is possible to get smoother (non bursty)
> throughput. It also corrects the bug where a delay of 0 would always cause
> a delay of 1 tick.
>
> Signed-off-by: Stephen Hemminger <shemminger@xxxxxxxx>
>
> --- linux-2.6.12-rc2/net/sched/sch_netem.c    2005-04-04 09:39:41.000000000
> -0700
> +++ netem/net/sched/sch_netem.c       2005-04-06 15:54:09.514780384 -0700
> @@ -138,38 +138,78 @@
>  }
>
>  /* Put skb in the private delayed queue. */
> -static int delay_skb(struct Qdisc *sch, struct sk_buff *skb)
> +static int netem_delay(struct Qdisc *sch, struct sk_buff *skb)
>  {
>       struct netem_sched_data *q = qdisc_priv(sch);
> -     struct netem_skb_cb *cb = (struct netem_skb_cb *)skb->cb;
>       psched_tdiff_t td;
>       psched_time_t now;
>
>       PSCHED_GET_TIME(now);
>       td = tabledist(q->latency, q->jitter, &q->delay_cor, q->delay_dist);
> -     PSCHED_TADD2(now, td, cb->time_to_send);
>
>       /* Always queue at tail to keep packets in order */
>       if (likely(q->delayed.qlen < q->limit)) {
> +             struct netem_skb_cb *cb = (struct netem_skb_cb *)skb->cb;
> +
> +             PSCHED_TADD2(now, td, cb->time_to_send);
> +
> +             pr_debug("netem_delay: skb=%p now=%llu tosend=%llu\n", skb,
> +                      now, cb->time_to_send);
> +
>               __skb_queue_tail(&q->delayed, skb);
> -             if (!timer_pending(&q->timer)) {
> -                     q->timer.expires = jiffies + PSCHED_US2JIFFIE(td);
> -                     add_timer(&q->timer);
> -             }
>               return NET_XMIT_SUCCESS;
>       }
>
> +     pr_debug("netem_delay: queue over limit %d\n", q->limit);
> +     sch->qstats.overlimits++;
>       kfree_skb(skb);
>       return NET_XMIT_DROP;
>  }
>
> +/*
> + *  Move a packet that is ready to send from the delay holding
> + *  list to the underlying qdisc.
> + */
> +static int netem_run(struct Qdisc *sch)
> +{
> +     struct netem_sched_data *q = qdisc_priv(sch);
> +     struct sk_buff *skb;
> +     psched_time_t now;
> +
> +     PSCHED_GET_TIME(now);
> +
> +     skb = skb_peek(&q->delayed);
> +     if (skb) {
> +             const struct netem_skb_cb *cb
> +                     = (const struct netem_skb_cb *)skb->cb;
> +             long delay
> +                     = PSCHED_US2JIFFIE(PSCHED_TDIFF(cb->time_to_send, now));
> +             pr_debug("netem_run: skb=%p delay=%ld\n", skb, delay);
> +
> +             /* if more time remaining? */
> +             if (delay > 0) {
> +                     mod_timer(&q->timer, jiffies + delay);
> +                     return 1;
> +             }
> +
> +             __skb_unlink(skb, &q->delayed);
> +
> +             if (q->qdisc->enqueue(skb, q->qdisc)) {
> +                     sch->q.qlen--;
> +                     sch->qstats.drops++;
> +             }
> +     }
> +
> +     return 0;
> +}
> +
>  static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
>  {
>       struct netem_sched_data *q = qdisc_priv(sch);
>       struct sk_buff *skb2;
>       int ret;
>
> -     pr_debug("netem_enqueue skb=%p @%lu\n", skb, jiffies);
> +     pr_debug("netem_enqueue skb=%p\n", skb);
>
>       /* Random packet drop 0 => none, ~0 => all */
>       if (q->loss && q->loss >= get_crandom(&q->loss_cor)) {
> @@ -184,7 +224,7 @@
>           && (skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
>               pr_debug("netem_enqueue: dup %p\n", skb2);
>
> -             if (delay_skb(sch, skb2)) {
> +             if (netem_delay(sch, skb2)) {
>                       sch->q.qlen++;
>                       sch->bstats.bytes += skb2->len;
>                       sch->bstats.packets++;
> @@ -202,7 +242,8 @@
>               ret = q->qdisc->enqueue(skb, q->qdisc);
>       } else {
>               q->counter = 0;
> -             ret = delay_skb(sch, skb);
> +             ret = netem_delay(sch, skb);
> +             netem_run(sch);
>       }
>
>       if (likely(ret == NET_XMIT_SUCCESS)) {
> @@ -241,56 +282,35 @@
>       return len;
>  }
>
> -/* Dequeue packet.
> - *  Move all packets that are ready to send from the delay holding
> - *  list to the underlying qdisc, then just call dequeue
> - */
>  static struct sk_buff *netem_dequeue(struct Qdisc *sch)
>  {
>       struct netem_sched_data *q = qdisc_priv(sch);
>       struct sk_buff *skb;
> +     int pending;
> +
> +     pending = netem_run(sch);
>
>       skb = q->qdisc->dequeue(q->qdisc);
> -     if (skb)
> +     if (skb) {
> +             pr_debug("netem_dequeue: return skb=%p\n", skb);
>               sch->q.qlen--;
> +             sch->flags &= ~TCQ_F_THROTTLED;
> +     }
> +     else if (pending) {
> +             pr_debug("netem_dequeue: throttling\n");
> +             sch->flags |= TCQ_F_THROTTLED;
> +     }
> +
>       return skb;
>  }
>
>  static void netem_watchdog(unsigned long arg)
>  {
>       struct Qdisc *sch = (struct Qdisc *)arg;
> -     struct netem_sched_data *q = qdisc_priv(sch);
> -     struct net_device *dev = sch->dev;
> -     struct sk_buff *skb;
> -     psched_time_t now;
>
> -     pr_debug("netem_watchdog: fired @%lu\n", jiffies);
> -
> -     spin_lock_bh(&dev->queue_lock);
> -     PSCHED_GET_TIME(now);
> -
> -     while ((skb = skb_peek(&q->delayed)) != NULL) {
> -             const struct netem_skb_cb *cb
> -                     = (const struct netem_skb_cb *)skb->cb;
> -             long delay
> -                     = PSCHED_US2JIFFIE(PSCHED_TDIFF(cb->time_to_send, now));
> -             pr_debug("netem_watchdog: skb %p@%lu %ld\n",
> -                      skb, jiffies, delay);
> -
> -             /* if more time remaining? */
> -             if (delay > 0) {
> -                     mod_timer(&q->timer, jiffies + delay);
> -                     break;
> -             }
> -             __skb_unlink(skb, &q->delayed);
> -
> -             if (q->qdisc->enqueue(skb, q->qdisc)) {
> -                     sch->q.qlen--;
> -                     sch->qstats.drops++;
> -             }
> -     }
> -     qdisc_run(dev);
> -     spin_unlock_bh(&dev->queue_lock);
> +     pr_debug("netem_watchdog qlen=%d\n", sch->q.qlen);
> +     sch->flags &= ~TCQ_F_THROTTLED;
> +     netif_schedule(sch->dev);
>  }
>
>  static void netem_reset(struct Qdisc *sch)
> @@ -301,6 +321,7 @@
>       skb_queue_purge(&q->delayed);
>
>       sch->q.qlen = 0;
> +     sch->flags &= ~TCQ_F_THROTTLED;
>       del_timer_sync(&q->timer);
>  }
>
> _______________________________________________
> Netem mailing list
> Netem@xxxxxxxxxxxxxx
> http://lists.osdl.org/mailman/listinfo/netem
>



<Prev in Thread] Current Thread [Next in Thread>