summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2008-10-31 00:44:18 -0700
committerDavid S. Miller <davem@davemloft.net>2008-10-31 00:44:18 -0700
commit48a8f519e0fe22a5c98523286b2a120841a11dd5 (patch)
treeec70428b026091669bf1e23779f9cfdd1a1ca46f
parent90d841fd0a5e02affd4e2bbdde4f710c61599281 (diff)
pkt_sched: Add ->peek() methods for fifo, prio and SFQ qdiscs.
From: Patrick McHardy <kaber@trash.net> Just as a demonstration how easy adding a peek operation to the work-conserving qdiscs actually is. It doesn't need to keep or change any internal state in many cases thanks to the guarantee that the packet will either be dequeued or, if another packet arrives, the upper qdisc will immediately ->peek again to reevaluate the state. (This is only slightly modified Patrick's patch.) Signed-off-by: Jarek Poplawski <jarkao2@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/sch_generic.h5
-rw-r--r--net/sched/sch_fifo.c2
-rw-r--r--net/sched/sch_prio.c14
-rw-r--r--net/sched/sch_sfq.c12
4 files changed, 33 insertions, 0 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index f81f7c4d76f..da6839a7ff5 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -433,6 +433,11 @@ static inline struct sk_buff *qdisc_dequeue_tail(struct Qdisc *sch)
return __qdisc_dequeue_tail(sch, &sch->q);
}
+static inline struct sk_buff *qdisc_peek_head(struct Qdisc *sch)
+{
+ return skb_peek(&sch->q);
+}
+
static inline int __qdisc_requeue(struct sk_buff *skb, struct Qdisc *sch,
struct sk_buff_head *list)
{
diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c
index 23d258bfe8a..8825e8806f4 100644
--- a/net/sched/sch_fifo.c
+++ b/net/sched/sch_fifo.c
@@ -83,6 +83,7 @@ struct Qdisc_ops pfifo_qdisc_ops __read_mostly = {
.priv_size = sizeof(struct fifo_sched_data),
.enqueue = pfifo_enqueue,
.dequeue = qdisc_dequeue_head,
+ .peek = qdisc_peek_head,
.requeue = qdisc_requeue,
.drop = qdisc_queue_drop,
.init = fifo_init,
@@ -98,6 +99,7 @@ struct Qdisc_ops bfifo_qdisc_ops __read_mostly = {
.priv_size = sizeof(struct fifo_sched_data),
.enqueue = bfifo_enqueue,
.dequeue = qdisc_dequeue_head,
+ .peek = qdisc_peek_head,
.requeue = qdisc_requeue,
.drop = qdisc_queue_drop,
.init = fifo_init,
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index 504a78cdb71..3651da3e280 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -120,6 +120,19 @@ prio_requeue(struct sk_buff *skb, struct Qdisc* sch)
return ret;
}
+static struct sk_buff *prio_peek(struct Qdisc *sch)
+{
+ struct prio_sched_data *q = qdisc_priv(sch);
+ int prio;
+
+ for (prio = 0; prio < q->bands; prio++) {
+ struct Qdisc *qdisc = q->queues[prio];
+ struct sk_buff *skb = qdisc->ops->peek(qdisc);
+ if (skb)
+ return skb;
+ }
+ return NULL;
+}
static struct sk_buff *prio_dequeue(struct Qdisc* sch)
{
@@ -421,6 +434,7 @@ static struct Qdisc_ops prio_qdisc_ops __read_mostly = {
.priv_size = sizeof(struct prio_sched_data),
.enqueue = prio_enqueue,
.dequeue = prio_dequeue,
+ .peek = prio_peek,
.requeue = prio_requeue,
.drop = prio_drop,
.init = prio_init,
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index fe1508ef0d3..198b83d42ba 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -391,8 +391,19 @@ sfq_requeue(struct sk_buff *skb, struct Qdisc *sch)
return NET_XMIT_CN;
}
+static struct sk_buff *
+sfq_peek(struct Qdisc *sch)
+{
+ struct sfq_sched_data *q = qdisc_priv(sch);
+ sfq_index a;
+ /* No active slots */
+ if (q->tail == SFQ_DEPTH)
+ return NULL;
+ a = q->next[q->tail];
+ return skb_peek(&q->qs[a]);
+}
static struct sk_buff *
sfq_dequeue(struct Qdisc *sch)
@@ -624,6 +635,7 @@ static struct Qdisc_ops sfq_qdisc_ops __read_mostly = {
.priv_size = sizeof(struct sfq_sched_data),
.enqueue = sfq_enqueue,
.dequeue = sfq_dequeue,
+ .peek = sfq_peek,
.requeue = sfq_requeue,
.drop = sfq_drop,
.init = sfq_init,