pkt_sched: Add qdisc->ops->peek() implementation.
authorJarek Poplawski <jarkao2@gmail.com>
Fri, 31 Oct 2008 07:45:55 +0000 (00:45 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 31 Oct 2008 07:45:55 +0000 (00:45 -0700)
Add qdisc->ops->peek() implementation for work-conserving qdiscs.
With feedback from Patrick McHardy.

Signed-off-by: Jarek Poplawski <jarkao2@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/sched/sch_atm.c
net/sched/sch_blackhole.c
net/sched/sch_dsmark.c
net/sched/sch_gred.c
net/sched/sch_multiq.c
net/sched/sch_netem.c
net/sched/sch_red.c
net/sched/sch_teql.c

index 43d37256c15e3864655364ee96822a834266b89e..f9eac0818d1814966e8362bedc8e49225f9981f9 100644 (file)
@@ -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,
index 507fb488bc985a18d13e0d79d95720b704118153..094a874b48bc43ca9337887bdd7cf462ee0ea63f 100644 (file)
@@ -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,
 };
 
index ba43aab3a8515ed3a71925254a4a531849665baa..3e491479ea86e7090a469fdb5cc31231ec3c728d 100644 (file)
@@ -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,
index c1ad6b8de105a60bbb4427d8f49e47b7e5adc46e..cb20ee3b9fc255dc86bf4d4a16d9a6b25a4b4b96 100644 (file)
@@ -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,
index 915f3149dde23c6d5391d505ae957714961cd2d1..155648d23b7cb5a2ed3918f1a097a0fc1de0b42a 100644 (file)
@@ -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,
index a11959908d9a68c405114d56c5073c0d77647402..2898d9dc31eb2548cc24a16052ed055b9fb35234 100644 (file)
@@ -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,
index 5da05839e225001bd9afeae5e6ba975a96fc3da1..7abc51454c2d4026974fd674b931d5715032e18b 100644 (file)
@@ -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,
index d35ef059abb1781e41becb98e6b1a15e3596001b..bf03e7fa184953b6112554f829bb691ceb9643df 100644 (file)
@@ -123,6 +123,13 @@ teql_dequeue(struct Qdisc* sch)
        return skb;
 }
 
+static struct sk_buff *
+teql_peek(struct Qdisc* sch)
+{
+       /* teql is meant to be used as root qdisc */
+       return NULL;
+}
+
 static __inline__ void
 teql_neigh_release(struct neighbour *n)
 {
@@ -433,6 +440,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;