Patchwork [4/6] pkt_sched: Add qdisc->ops->peek() implementation.

login
register
mail settings
Submitter Jarek Poplawski
Date Oct. 16, 2008, 9:48 a.m.
Message ID <20081016094804.GE19019@ff.dom.local>
Download mbox | patch
Permalink /patch/4676/
State Deferred
Delegated to: David Miller
Headers show

Comments

Jarek Poplawski - Oct. 16, 2008, 9:48 a.m.
Add qdisc->ops->peek() implementation for work-conserving qdiscs.

Signed-off-by: Jarek Poplawski <jarkao2@gmail.com>
---
 net/sched/sch_atm.c       |   10 ++++++++++
 net/sched/sch_blackhole.c |    1 +
 net/sched/sch_dsmark.c    |   10 ++++++++++
 net/sched/sch_gred.c      |    1 +
 net/sched/sch_multiq.c    |   29 +++++++++++++++++++++++++++++
 net/sched/sch_netem.c     |    1 +
 net/sched/sch_red.c       |    9 +++++++++
 net/sched/sch_teql.c      |    9 +++++++++
 8 files changed, 70 insertions(+), 0 deletions(-)
Patrick McHardy - Oct. 16, 2008, 12:26 p.m.
Jarek Poplawski wrote:
> Add qdisc->ops->peek() implementation for work-conserving qdiscs.
> 
> diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c
> index 915f314..155648d 100644
> --- a/net/sched/sch_multiq.c
> +++ b/net/sched/sch_multiq.c

I haven't looked at sch_multiq in detail yet, but isn't it supposed to
be used as root qdisc? In that case we wouldn't need a ->peek operation.

> diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
> index d35ef05..8d7acd8 100644
> --- a/net/sched/sch_teql.c
> +++ b/net/sched/sch_teql.c

teql is also meant to be used as root qdisc. It doesn't seem to enfore
it though.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jarek Poplawski - Oct. 16, 2008, 12:54 p.m.
On Thu, Oct 16, 2008 at 02:26:33PM +0200, Patrick McHardy wrote:
> Jarek Poplawski wrote:
>> Add qdisc->ops->peek() implementation for work-conserving qdiscs.
>>
>> diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c
>> index 915f314..155648d 100644
>> --- a/net/sched/sch_multiq.c
>> +++ b/net/sched/sch_multiq.c
>
> I haven't looked at sch_multiq in detail yet, but isn't it supposed to
> be used as root qdisc? In that case we wouldn't need a ->peek operation.
>

It's recommended, but IMHO, could be useful as a child too, especially
for testing. I've thought if it shouldn't be rather treated as non-work-
conserving, but I don't think there is a reason for preventing such test
or other non-optimal usage.

>> diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
>> index d35ef05..8d7acd8 100644
>> --- a/net/sched/sch_teql.c
>> +++ b/net/sched/sch_teql.c
>
> teql is also meant to be used as root qdisc. It doesn't seem to enfore
> it though.

Probably like above: there is not much of this code, but it could be
cut, no problem.

Jarek P.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Patrick McHardy - Oct. 16, 2008, 1 p.m.
Jarek Poplawski wrote:
> On Thu, Oct 16, 2008 at 02:26:33PM +0200, Patrick McHardy wrote:
>> Jarek Poplawski wrote:
>>> Add qdisc->ops->peek() implementation for work-conserving qdiscs.
>>>
>>> diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c
>>> index 915f314..155648d 100644
>>> --- a/net/sched/sch_multiq.c
>>> +++ b/net/sched/sch_multiq.c
>> I haven't looked at sch_multiq in detail yet, but isn't it supposed to
>> be used as root qdisc? In that case we wouldn't need a ->peek operation.
>>
> 
> It's recommended, but IMHO, could be useful as a child too, especially
> for testing. I've thought if it shouldn't be rather treated as non-work-
> conserving, but I don't think there is a reason for preventing such test
> or other non-optimal usage.

OK, if it works thats fine of course.

>>> diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
>>> index d35ef05..8d7acd8 100644
>>> --- a/net/sched/sch_teql.c
>>> +++ b/net/sched/sch_teql.c
>> teql is also meant to be used as root qdisc. It doesn't seem to enfore
>> it though.
> 
> Probably like above: there is not much of this code, but it could be
> cut, no problem.

I'm mainly wondering whether it works at all when not used as a
root qdisc. I'm unable to answer this by a quick look at the code,
so for now I'd just keep that part too.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index 43d3725..f9eac08 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -522,6 +522,15 @@  static struct sk_buff *atm_tc_dequeue(struct Qdisc *sch)
 	return skb;
 }
 
+static struct sk_buff *atm_tc_peek(struct Qdisc *sch)
+{
+	struct atm_qdisc_data *p = qdisc_priv(sch);
+
+	pr_debug("atm_tc_peek(sch %p,[qdisc %p])\n", sch, p);
+
+	return p->link.q->ops->peek(p->link.q);
+}
+
 static int atm_tc_requeue(struct sk_buff *skb, struct Qdisc *sch)
 {
 	struct atm_qdisc_data *p = qdisc_priv(sch);
@@ -694,6 +703,7 @@  static struct Qdisc_ops atm_qdisc_ops __read_mostly = {
 	.priv_size	= sizeof(struct atm_qdisc_data),
 	.enqueue	= atm_tc_enqueue,
 	.dequeue	= atm_tc_dequeue,
+	.peek		= atm_tc_peek,
 	.requeue	= atm_tc_requeue,
 	.drop		= atm_tc_drop,
 	.init		= atm_tc_init,
diff --git a/net/sched/sch_blackhole.c b/net/sched/sch_blackhole.c
index 507fb48..094a874 100644
--- a/net/sched/sch_blackhole.c
+++ b/net/sched/sch_blackhole.c
@@ -33,6 +33,7 @@  static struct Qdisc_ops blackhole_qdisc_ops __read_mostly = {
 	.priv_size	= 0,
 	.enqueue	= blackhole_enqueue,
 	.dequeue	= blackhole_dequeue,
+	.peek		= blackhole_dequeue,
 	.owner		= THIS_MODULE,
 };
 
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index ba43aab..3e49147 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -313,6 +313,15 @@  static struct sk_buff *dsmark_dequeue(struct Qdisc *sch)
 	return skb;
 }
 
+static struct sk_buff *dsmark_peek(struct Qdisc *sch)
+{
+	struct dsmark_qdisc_data *p = qdisc_priv(sch);
+
+	pr_debug("dsmark_peek(sch %p,[qdisc %p])\n", sch, p);
+
+	return p->q->ops->peek(p->q);
+}
+
 static int dsmark_requeue(struct sk_buff *skb, struct Qdisc *sch)
 {
 	struct dsmark_qdisc_data *p = qdisc_priv(sch);
@@ -496,6 +505,7 @@  static struct Qdisc_ops dsmark_qdisc_ops __read_mostly = {
 	.priv_size	=	sizeof(struct dsmark_qdisc_data),
 	.enqueue	=	dsmark_enqueue,
 	.dequeue	=	dsmark_dequeue,
+	.peek		=	dsmark_peek,
 	.requeue	=	dsmark_requeue,
 	.drop		=	dsmark_drop,
 	.init		=	dsmark_init,
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index c1ad6b8..cb20ee3 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -602,6 +602,7 @@  static struct Qdisc_ops gred_qdisc_ops __read_mostly = {
 	.priv_size	=	sizeof(struct gred_sched),
 	.enqueue	=	gred_enqueue,
 	.dequeue	=	gred_dequeue,
+	.peek		=	qdisc_peek_head,
 	.requeue	=	gred_requeue,
 	.drop		=	gred_drop,
 	.init		=	gred_init,
diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c
index 915f314..155648d 100644
--- a/net/sched/sch_multiq.c
+++ b/net/sched/sch_multiq.c
@@ -155,6 +155,34 @@  static struct sk_buff *multiq_dequeue(struct Qdisc *sch)
 
 }
 
+static struct sk_buff *multiq_peek(struct Qdisc *sch)
+{
+	struct multiq_sched_data *q = qdisc_priv(sch);
+	unsigned int curband = q->curband;
+	struct Qdisc *qdisc;
+	struct sk_buff *skb;
+	int band;
+
+	for (band = 0; band < q->bands; band++) {
+		/* cycle through bands to ensure fairness */
+		curband++;
+		if (curband >= q->bands)
+			curband = 0;
+
+		/* Check that target subqueue is available before
+		 * pulling an skb to avoid excessive requeues
+		 */
+		if (!__netif_subqueue_stopped(qdisc_dev(sch), curband)) {
+			qdisc = q->queues[curband];
+			skb = qdisc->ops->peek(qdisc);
+			if (skb)
+				return skb;
+		}
+	}
+	return NULL;
+
+}
+
 static unsigned int multiq_drop(struct Qdisc *sch)
 {
 	struct multiq_sched_data *q = qdisc_priv(sch);
@@ -451,6 +479,7 @@  static struct Qdisc_ops multiq_qdisc_ops __read_mostly = {
 	.priv_size	=	sizeof(struct multiq_sched_data),
 	.enqueue	=	multiq_enqueue,
 	.dequeue	=	multiq_dequeue,
+	.peek		=	multiq_peek,
 	.requeue	=	multiq_requeue,
 	.drop		=	multiq_drop,
 	.init		=	multiq_init,
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index a119599..2898d9d 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -541,6 +541,7 @@  static struct Qdisc_ops tfifo_qdisc_ops __read_mostly = {
 	.priv_size	=	sizeof(struct fifo_sched_data),
 	.enqueue	=	tfifo_enqueue,
 	.dequeue	=	qdisc_dequeue_head,
+	.peek		=	qdisc_peek_head,
 	.requeue	=	qdisc_requeue,
 	.drop		=	qdisc_queue_drop,
 	.init		=	tfifo_init,
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index 5da0583..7abc514 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -140,6 +140,14 @@  static struct sk_buff * red_dequeue(struct Qdisc* sch)
 	return skb;
 }
 
+static struct sk_buff * red_peek(struct Qdisc* sch)
+{
+	struct red_sched_data *q = qdisc_priv(sch);
+	struct Qdisc *child = q->qdisc;
+
+	return child->ops->peek(child);
+}
+
 static unsigned int red_drop(struct Qdisc* sch)
 {
 	struct red_sched_data *q = qdisc_priv(sch);
@@ -361,6 +369,7 @@  static struct Qdisc_ops red_qdisc_ops __read_mostly = {
 	.cl_ops		=	&red_class_ops,
 	.enqueue	=	red_enqueue,
 	.dequeue	=	red_dequeue,
+	.peek		=	red_peek,
 	.requeue	=	red_requeue,
 	.drop		=	red_drop,
 	.init		=	red_init,
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index d35ef05..8d7acd8 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -123,6 +123,14 @@  teql_dequeue(struct Qdisc* sch)
 	return skb;
 }
 
+static struct sk_buff *
+teql_peek(struct Qdisc* sch)
+{
+	struct teql_sched_data *dat = qdisc_priv(sch);
+
+	return skb_peek(&dat->q);
+}
+
 static __inline__ void
 teql_neigh_release(struct neighbour *n)
 {
@@ -433,6 +441,7 @@  static __init void teql_master_setup(struct net_device *dev)
 
 	ops->enqueue	=	teql_enqueue;
 	ops->dequeue	=	teql_dequeue;
+	ops->peek	=	teql_peek;
 	ops->requeue	=	teql_requeue;
 	ops->init	=	teql_qdisc_init;
 	ops->reset	=	teql_reset;