patch-2.1.79 linux/net/sched/sch_generic.c

Next file: linux/net/socket.c
Previous file: linux/net/sched/Config.in
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.78/linux/net/sched/sch_generic.c linux/net/sched/sch_generic.c
@@ -34,6 +34,9 @@
 
 static struct Qdisc_ops *qdisc_base = NULL;
 
+static int default_requeue(struct sk_buff *skb, struct Qdisc* qdisc);
+
+
 /* NOTES.
 
    Every discipline has two major routines: enqueue and dequeue.
@@ -75,6 +78,8 @@
 			break;
 	if (!q)
 		return -ENOENT;
+	if (q->requeue == NULL)
+		q->requeue = default_requeue;
 	*qp = q->next;
 	return 0;
 }
@@ -118,6 +123,7 @@
 };
 
 
+
 /* 3-band FIFO queue: old style, but should be a bit faster (several CPU insns) */
 
 static int
@@ -129,7 +135,7 @@
 	list = ((struct sk_buff_head*)qdisc->data) + prio2band[skb->priority&7];
 
 	if (list->qlen <= skb->dev->tx_queue_len) {
-		skb_queue_tail(list, skb);
+		__skb_queue_tail(list, skb);
 		return 1;
 	}
 	qdisc->dropped++;
@@ -145,13 +151,25 @@
 	struct sk_buff *skb;
 
 	for (prio = 0; prio < 3; prio++, list++) {
-		skb = skb_dequeue(list);
+		skb = __skb_dequeue(list);
 		if (skb)
 			return skb;
 	}
 	return NULL;
 }
 
+static int
+pfifo_fast_requeue(struct sk_buff *skb, struct Qdisc* qdisc)
+{
+	const static u8 prio2band[8] = { 1, 2, 2, 2, 1, 2, 0, 0 };
+	struct sk_buff_head *list;
+
+	list = ((struct sk_buff_head*)qdisc->data) + prio2band[skb->priority&7];
+
+	__skb_queue_head(list, skb);
+	return 1;
+}
+
 static void
 pfifo_fast_reset(struct Qdisc* qdisc)
 {
@@ -185,9 +203,20 @@
 	pfifo_fast_dequeue,
 	pfifo_fast_reset,
 	NULL,
-	pfifo_fast_init
+	pfifo_fast_init,
+	NULL,
+	pfifo_fast_requeue
 };
 
+static int
+default_requeue(struct sk_buff *skb, struct Qdisc* qdisc)
+{
+	if (net_ratelimit())
+		printk(KERN_DEBUG "%s deferred output. It is buggy.\n", skb->dev->name);
+	kfree_skb(skb, FREE_WRITE);
+	return 0;
+}
+
 static struct Qdisc *
 qdisc_alloc(struct device *dev, struct Qdisc_ops *ops, void *arg)
 {
@@ -200,7 +229,6 @@
 	memset(sch, 0, size);
 
 	skb_queue_head_init(&sch->q);
-	skb_queue_head_init(&sch->failure_q);
 	sch->ops = ops;
 	sch->enqueue = ops->enqueue;
 	sch->dequeue = ops->dequeue;
@@ -218,7 +246,6 @@
 		start_bh_atomic();
 		if (ops->reset)
 			ops->reset(qdisc);
-		skb_queue_purge(&qdisc->failure_q);
 		end_bh_atomic();
 	}
 }
@@ -232,7 +259,6 @@
 			ops->reset(qdisc);
 		if (ops->destroy)
 			ops->destroy(qdisc);
-		skb_queue_purge(&qdisc->failure_q);
 		ops->refcnt--;
 		end_bh_atomic();
 		kfree(qdisc);
@@ -373,23 +399,22 @@
 	struct Qdisc *q = dev->qdisc;
 	struct sk_buff *skb;
 
-	skb = skb_dequeue(&q->failure_q);
-	if (!skb) {
-		skb = q->dequeue(q);
-		if (netdev_nit && skb)
-			dev_queue_xmit_nit(skb,dev);
-	}
-	if (skb) {
+	if ((skb = q->dequeue(q)) != NULL) {
+		if (netdev_nit)
+			dev_queue_xmit_nit(skb, dev);
+
 		if (dev->hard_start_xmit(skb, dev) == 0) {
 			q->tx_last = jiffies;
 			return -1;
 		}
-#if 0
-		if (net_ratelimit())
-			printk(KERN_DEBUG "netdevice %s defers output.\n", dev->name);
-#endif
-		skb_queue_head(&q->failure_q, skb);
-		return -1;
+
+		if (q->ops) {
+			q->ops->requeue(skb, q);
+			return -1;
+		}
+
+		printk(KERN_DEBUG "%s: it is impossible!!!\n", dev->name);
+		kfree_skb(skb, FREE_WRITE);
 	}
 	return q->q.qlen;
 }
@@ -510,9 +535,6 @@
           extern struct Qdisc_ops name##_ops; \
           register_qdisc(&##name##_ops); \
 	}
-
-	skb_queue_head_init(&noop_qdisc.failure_q);
-	skb_queue_head_init(&noqueue_qdisc.failure_q);
 
 	register_qdisc(&pfifo_fast_ops);
 #ifdef CONFIG_NET_SCH_CBQ

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov