aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/sched/sch_netem.c34
1 files changed, 22 insertions, 12 deletions
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index bb9bf8d5003c..d871fe7f81a9 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -185,10 +185,13 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
185 || q->counter < q->gap /* inside last reordering gap */ 185 || q->counter < q->gap /* inside last reordering gap */
186 || q->reorder < get_crandom(&q->reorder_cor)) { 186 || q->reorder < get_crandom(&q->reorder_cor)) {
187 psched_time_t now; 187 psched_time_t now;
188 psched_tdiff_t delay;
189
190 delay = tabledist(q->latency, q->jitter,
191 &q->delay_cor, q->delay_dist);
192
188 PSCHED_GET_TIME(now); 193 PSCHED_GET_TIME(now);
189 PSCHED_TADD2(now, tabledist(q->latency, q->jitter, 194 PSCHED_TADD2(now, delay, cb->time_to_send);
190 &q->delay_cor, q->delay_dist),
191 cb->time_to_send);
192 ++q->counter; 195 ++q->counter;
193 ret = q->qdisc->enqueue(skb, q->qdisc); 196 ret = q->qdisc->enqueue(skb, q->qdisc);
194 } else { 197 } else {
@@ -248,24 +251,31 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
248 const struct netem_skb_cb *cb 251 const struct netem_skb_cb *cb
249 = (const struct netem_skb_cb *)skb->cb; 252 = (const struct netem_skb_cb *)skb->cb;
250 psched_time_t now; 253 psched_time_t now;
251 long delay;
252 254
253 /* if more time remaining? */ 255 /* if more time remaining? */
254 PSCHED_GET_TIME(now); 256 PSCHED_GET_TIME(now);
255 delay = PSCHED_US2JIFFIE(PSCHED_TDIFF(cb->time_to_send, now)); 257
256 pr_debug("netem_run: skb=%p delay=%ld\n", skb, delay); 258 if (PSCHED_TLESS(cb->time_to_send, now)) {
257 if (delay <= 0) {
258 pr_debug("netem_dequeue: return skb=%p\n", skb); 259 pr_debug("netem_dequeue: return skb=%p\n", skb);
259 sch->q.qlen--; 260 sch->q.qlen--;
260 sch->flags &= ~TCQ_F_THROTTLED; 261 sch->flags &= ~TCQ_F_THROTTLED;
261 return skb; 262 return skb;
262 } 263 } else {
264 psched_tdiff_t delay = PSCHED_TDIFF(cb->time_to_send, now);
263 265
264 mod_timer(&q->timer, jiffies + delay); 266 if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) {
265 sch->flags |= TCQ_F_THROTTLED; 267 sch->qstats.drops++;
266 268
267 if (q->qdisc->ops->requeue(skb, q->qdisc) != 0) 269 /* After this qlen is confused */
268 sch->qstats.drops++; 270 printk(KERN_ERR "netem: queue discpline %s could not requeue\n",
271 q->qdisc->ops->id);
272
273 sch->q.qlen--;
274 }
275
276 mod_timer(&q->timer, jiffies + PSCHED_US2JIFFIE(delay));
277 sch->flags |= TCQ_F_THROTTLED;
278 }
269 } 279 }
270 280
271 return NULL; 281 return NULL;