diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/sched/sch_netem.c | 34 |
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; |
