diff -ur sch_sfb/sch_sfb.c sch_sfb-compat-2.6.26/sch_sfb.c --- sch_sfb/sch_sfb.c 2009-11-09 02:08:59.000000000 +0100 +++ sch_sfb-compat-2.6.26/sch_sfb.c 2009-11-09 21:08:47.000000000 +0100 @@ -96,7 +96,7 @@ default: h = skb->protocol; if(hash_type != SFB_HASH_SOURCE) - h ^= (u32)(unsigned long)skb_dst(skb); + h ^= (u32)(unsigned long)skb->dst; h2 = hash_type == SFB_HASH_FLOW ? (u32)(unsigned long)skb->sk : 0; } @@ -334,14 +334,14 @@ } enqueue: - ret = qdisc_enqueue(skb, child); + ret = child->enqueue(skb, child); if(likely(ret == NET_XMIT_SUCCESS)) { sch->q.qlen++; increment_qlen(skb, q); sch->bstats.packets++; sch->bstats.bytes += skb->len; sch->qstats.backlog += skb->len; - } else if(net_xmit_drop_count(ret)) { + } else { q->queuedrop++; sch->qstats.drops++; } @@ -369,12 +369,23 @@ return skb; } -static struct sk_buff *sfb_peek(struct Qdisc* sch) +static int sfb_requeue(struct sk_buff *skb, struct Qdisc* sch) { - struct sfb_sched_data *q = qdisc_priv(sch); - struct Qdisc *child = q->qdisc; + struct sfb_sched_data *q = qdisc_priv(sch); + struct Qdisc *child = q->qdisc; + int ret; + + ret = child->ops->requeue(skb, child); + if(unlikely(ret != NET_XMIT_SUCCESS)) { + sch->qstats.drops++; + return ret; + } - return child->ops->peek(child); + sch->q.qlen++; + increment_qlen(skb, q); + sch->qstats.backlog += skb->len; + sch->qstats.requeues++; + return ret; } /* No sfb_drop -- impossible since the child doesn't return the dropped skb. */ @@ -400,6 +411,33 @@ q->qdisc = NULL; } +static struct Qdisc *sfb_create_dflt(struct Qdisc *sch, u32 limit) +{ + struct Qdisc *q; + struct nlattr *nla; + int ret; + + q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, + TC_H_MAKE(sch->handle, 1)); + if (q) { + nla = kmalloc(nla_attr_size(sizeof(struct tc_fifo_qopt)), + GFP_KERNEL); + if (nla) { + nla->nla_type = RTM_NEWQDISC; + nla->nla_len = nla_attr_size(sizeof(struct tc_fifo_qopt)); + ((struct tc_fifo_qopt *)nla_data(nla))->limit = limit; + + ret = q->ops->change(q, nla); + kfree(nla); + + if (ret == 0) + return q; + } + qdisc_destroy(q); + } + return NULL; +} + static const struct nla_policy sfb_policy[TCA_SFB_MAX + 1] = { [TCA_SFB_PARMS] = { .len = sizeof(struct tc_sfb_qopt) }, }; @@ -462,11 +500,11 @@ if(hash_type >= __SFB_HASH_MAX) hash_type = SFB_HASH_FLOW; if(limit == 0) - limit = qdisc_dev(sch)->tx_queue_len; + limit = sch->dev->tx_queue_len; if(limit == 0) limit = 1; - child = fifo_create_dflt(sch, &pfifo_qdisc_ops, limit); + child = sfb_create_dflt(sch, limit); if(IS_ERR(child)) return PTR_ERR(child); @@ -636,7 +674,7 @@ .cl_ops = &sfb_class_ops, .enqueue = sfb_enqueue, .dequeue = sfb_dequeue, - .peek = sfb_peek, + .requeue = sfb_requeue, .init = sfb_init, .reset = sfb_reset, .destroy = sfb_destroy,