Commit 096acddf authored by Patrick McHardy's avatar Patrick McHardy

[NET_SCHED]: Fix requeueing in HFSC scheduler.

Requeued packets are kept in a high-priority queue
which is always dequeued first.
parent 18a678c4
......@@ -181,12 +181,11 @@ struct hfsc_sched
{
u16 defcls; /* default class id */
struct hfsc_class root; /* root class */
struct hfsc_class *last_xmit; /* class that transmitted last
packet (for requeueing) */
struct list_head clhash[HFSC_HSIZE]; /* class hash */
struct list_head eligible; /* eligible list */
struct list_head droplist; /* active leaf class list (for
dropping) */
struct sk_buff_head requeue; /* requeued packet */
struct timer_list wd_timer; /* watchdog timer */
};
......@@ -1228,9 +1227,6 @@ hfsc_delete_class(struct Qdisc *sch, unsigned long arg)
list_del(&cl->siblings);
hfsc_adjust_levels(cl->cl_parent);
hfsc_purge_queue(sch, cl);
if (q->last_xmit == cl)
q->last_xmit = NULL;
if (--cl->refcnt == 0)
hfsc_destroy_class(sch, cl);
......@@ -1538,6 +1534,7 @@ hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt)
INIT_LIST_HEAD(&q->clhash[i]);
INIT_LIST_HEAD(&q->eligible);
INIT_LIST_HEAD(&q->droplist);
skb_queue_head_init(&q->requeue);
q->root.refcnt = 1;
q->root.classid = sch->handle;
......@@ -1616,10 +1613,9 @@ hfsc_reset_qdisc(struct Qdisc *sch)
list_for_each_entry(cl, &q->clhash[i], hlist)
hfsc_reset_class(cl);
}
__skb_queue_purge(&q->requeue);
INIT_LIST_HEAD(&q->eligible);
INIT_LIST_HEAD(&q->droplist);
q->last_xmit = NULL;
del_timer(&q->wd_timer);
sch->flags &= ~TCQ_F_THROTTLED;
sch->q.qlen = 0;
......@@ -1636,7 +1632,7 @@ hfsc_destroy_qdisc(struct Qdisc *sch)
list_for_each_entry_safe(cl, next, &q->clhash[i], hlist)
hfsc_destroy_class(sch, cl);
}
__skb_queue_purge(&q->requeue);
del_timer(&q->wd_timer);
}
......@@ -1705,6 +1701,8 @@ hfsc_dequeue(struct Qdisc *sch)
if (sch->q.qlen == 0)
return NULL;
if ((skb = __skb_dequeue(&q->requeue)))
goto out;
PSCHED_GET_TIME(cur_time);
......@@ -1754,7 +1752,7 @@ hfsc_dequeue(struct Qdisc *sch)
set_passive(cl);
}
q->last_xmit = cl;
out:
sch->flags &= ~TCQ_F_THROTTLED;
sch->q.qlen--;
......@@ -1765,28 +1763,10 @@ static int
hfsc_requeue(struct sk_buff *skb, struct Qdisc *sch)
{
struct hfsc_sched *q = (struct hfsc_sched *)sch->data;
struct hfsc_class *cl = q->last_xmit;
unsigned int len = skb->len;
int ret;
if (cl == NULL) {
kfree_skb(skb);
sch->stats.drops++;
return NET_XMIT_DROP;
}
ret = cl->qdisc->ops->requeue(skb, cl->qdisc);
if (ret == NET_XMIT_SUCCESS) {
if (cl->qdisc->q.qlen == 1)
set_active(cl, len);
sch->q.qlen++;
} else {
cl->stats.drops++;
sch->stats.drops++;
}
q->last_xmit = NULL;
return ret;
__skb_queue_head(&q->requeue, skb);
sch->q.qlen++;
return NET_XMIT_SUCCESS;
}
static unsigned int
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment