[NET_SCHED]: Fix endless loops (part 5): netem/tbf/hfsc ->requeue failures
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>
This commit is contained in:
parent
256d61b87b
commit
e488eafcc5
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue