Skip to content

Commit

Permalink
[NET_SCHED]: Fix endless loops (part 5): netem/tbf/hfsc ->requeue fai…
Browse files Browse the repository at this point in the history
…lures

When peeking at the next packet in a child qdisc by calling dequeue/requeue,
the upper qdisc qlen counter may get out of sync in case the requeue fails.
The qdisc and the child qdisc both have their counter decremented, but since
no packet is given to the upper qdisc it won't decrement its counter itself.

requeue should not fail, so this is mostly for "correctness".

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Patrick McHardy authored and David S. Miller committed Dec 3, 2006
1 parent 256d61b commit e488eaf
Show file tree
Hide file tree
Showing 3 changed files with 3 additions and 5 deletions.
1 change: 1 addition & 0 deletions net/sched/sch_hfsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,7 @@ qdisc_peek_len(struct Qdisc *sch)
if (unlikely(sch->ops->requeue(skb, sch) != NET_XMIT_SUCCESS)) {
if (net_ratelimit())
printk("qdisc_peek_len: failed to requeue\n");
qdisc_tree_decrease_qlen(sch, 1);
return 0;
}
return len;
Expand Down
5 changes: 1 addition & 4 deletions net/sched/sch_netem.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,13 +287,10 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
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++;

/* After this qlen is confused */
printk(KERN_ERR "netem: queue discpline %s could not requeue\n",
q->qdisc->ops->id);

sch->q.qlen--;
}

mod_timer(&q->timer, jiffies + PSCHED_US2JIFFIE(delay));
Expand Down
2 changes: 1 addition & 1 deletion net/sched/sch_tbf.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch)

if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) {
/* When requeue fails skb is dropped */
sch->q.qlen--;
qdisc_tree_decrease_qlen(q->qdisc, 1);
sch->qstats.drops++;
}

Expand Down

0 comments on commit e488eaf

Please sign in to comment.