From: Jarek Poplawski Date: Sun, 10 Feb 2008 07:44:00 +0000 (-0800) Subject: [NET_SCHED] sch_htb: htb_requeue fix X-Git-Tag: v2.6.25-rc1~7^2 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=21347456abfbf5bc7fcace7327476736bbb28abe;p=linux-2.6 [NET_SCHED] sch_htb: htb_requeue fix htb_requeue() enqueues skbs for which htb_classify() returns NULL. This is wrong because such skbs could be handled by NET_CLS_ACT code, and the decision could be different than earlier in htb_enqueue(). So htb_requeue() is changed to work and look more like htb_enqueue(). Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index e1a579efc2..795c761ad9 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -609,14 +609,14 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch) /* TODO: requeuing packet charges it to policers again !! */ static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch) { + int ret; struct htb_sched *q = qdisc_priv(sch); - int ret = NET_XMIT_SUCCESS; struct htb_class *cl = htb_classify(skb, sch, &ret); struct sk_buff *tskb; - if (cl == HTB_DIRECT || !cl) { + if (cl == HTB_DIRECT) { /* enqueue to helper queue */ - if (q->direct_queue.qlen < q->direct_qlen && cl) { + if (q->direct_queue.qlen < q->direct_qlen) { __skb_queue_head(&q->direct_queue, skb); } else { __skb_queue_head(&q->direct_queue, skb); @@ -625,6 +625,13 @@ static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch) sch->qstats.drops++; return NET_XMIT_CN; } +#ifdef CONFIG_NET_CLS_ACT + } else if (!cl) { + if (ret == NET_XMIT_BYPASS) + sch->qstats.drops++; + kfree_skb(skb); + return ret; +#endif } else if (cl->un.leaf.q->ops->requeue(skb, cl->un.leaf.q) != NET_XMIT_SUCCESS) { sch->qstats.drops++;