summaryrefslogtreecommitdiffstats
path: root/net/sched
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched')
-rw-r--r--net/sched/sch_gred.c68
1 files changed, 44 insertions, 24 deletions
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index 38dab959fee..646dbdc4ef2 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -176,20 +176,24 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch)
dp = tc_index_to_dp(skb);
if (dp >= t->DPs || (q = t->tab[dp]) == NULL) {
- printk("GRED: setting to default (%d)\n ",t->def);
- if (!(q=t->tab[t->def])) {
- DPRINTK("GRED: setting to default FAILED! dropping!! "
- "(%d)\n ", t->def);
- goto drop;
+ dp = t->def;
+
+ if ((q = t->tab[dp]) == NULL) {
+ /* Pass through packets not assigned to a DP
+ * if no default DP has been configured. This
+ * allows for DP flows to be left untouched.
+ */
+ if (skb_queue_len(&sch->q) < sch->dev->tx_queue_len)
+ return qdisc_enqueue_tail(skb, sch);
+ else
+ goto drop;
}
+
/* fix tc_index? --could be controvesial but needed for
requeueing */
- skb->tc_index=(skb->tc_index & ~GRED_VQ_MASK) | t->def;
+ skb->tc_index = (skb->tc_index & ~GRED_VQ_MASK) | dp;
}
- D2PRINTK("gred_enqueue virtualQ 0x%x classid %x backlog %d "
- "general backlog %d\n",skb->tc_index&0xf,sch->handle,q->backlog,
- sch->qstats.backlog);
/* sum up all the qaves of prios <= to ours to get the new qave*/
if (!gred_wred_mode(t) && gred_rio_mode(t)) {
for (i=0;i<t->DPs;i++) {
@@ -254,13 +258,20 @@ static int
gred_requeue(struct sk_buff *skb, struct Qdisc* sch)
{
struct gred_sched *t = qdisc_priv(sch);
- struct gred_sched_data *q = t->tab[tc_index_to_dp(skb)];
-/* error checking here -- probably unnecessary */
+ struct gred_sched_data *q;
+ u16 dp = tc_index_to_dp(skb);
- if (red_is_idling(&q->parms))
- red_end_of_idle_period(&q->parms);
+ if (dp >= t->DPs || (q = t->tab[dp]) == NULL) {
+ if (net_ratelimit())
+ printk(KERN_WARNING "GRED: Unable to relocate VQ 0x%x "
+ "for requeue, screwing up backlog.\n",
+ tc_index_to_dp(skb));
+ } else {
+ if (red_is_idling(&q->parms))
+ red_end_of_idle_period(&q->parms);
+ q->backlog += skb->len;
+ }
- q->backlog += skb->len;
return qdisc_requeue(skb, sch);
}
@@ -274,15 +285,20 @@ gred_dequeue(struct Qdisc* sch)
skb = qdisc_dequeue_head(sch);
if (skb) {
- q = t->tab[tc_index_to_dp(skb)];
- if (q) {
+ u16 dp = tc_index_to_dp(skb);
+
+ if (dp >= t->DPs || (q = t->tab[dp]) == NULL) {
+ if (net_ratelimit())
+ printk(KERN_WARNING "GRED: Unable to relocate "
+ "VQ 0x%x after dequeue, screwing up "
+ "backlog.\n", tc_index_to_dp(skb));
+ } else {
q->backlog -= skb->len;
+
if (!q->backlog && !gred_wred_mode(t))
red_start_of_idle_period(&q->parms);
- } else {
- D2PRINTK("gred_dequeue: skb has bad tcindex %x\n",
- tc_index_to_dp(skb));
}
+
return skb;
}
@@ -308,15 +324,19 @@ static unsigned int gred_drop(struct Qdisc* sch)
skb = qdisc_dequeue_tail(sch);
if (skb) {
unsigned int len = skb->len;
- q = t->tab[tc_index_to_dp(skb)];
- if (q) {
+ u16 dp = tc_index_to_dp(skb);
+
+ if (dp >= t->DPs || (q = t->tab[dp]) == NULL) {
+ if (net_ratelimit())
+ printk(KERN_WARNING "GRED: Unable to relocate "
+ "VQ 0x%x while dropping, screwing up "
+ "backlog.\n", tc_index_to_dp(skb));
+ } else {
q->backlog -= len;
q->stats.other++;
+
if (!q->backlog && !gred_wred_mode(t))
red_start_of_idle_period(&q->parms);
- } else {
- D2PRINTK("gred_dequeue: skb has bad tcindex %x\n",
- tc_index_to_dp(skb));
}
qdisc_drop(skb, sch);