diff options
author | Hagen Paul Pfeifer <hagen@jauu.net> | 2010-01-24 07:30:59 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-01-29 00:27:00 -0500 |
commit | 57dbb2d83d100ea601c54fe129bfde0678db5dee (patch) | |
tree | 40305bcd986692f512b1b5e848c0b0f612968c6a /net/sched | |
parent | d74340d31bf1dbeb00acadddd8697666528a7846 (diff) |
sched: add head drop fifo queue
This adds an additional queuing strategy, called pfifo_head_drop,
to remove the oldest skb in the case of an overflow within the queue -
the head element - instead of the last skb (tail). To remove the oldest
skb in congested situations is useful for sensor network environments
where newer packets reflect the superior information.
Reviewed-by: Florian Westphal <fw@strlen.de>
Acked-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Hagen Paul Pfeifer <hagen@jauu.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/sch_api.c | 1 | ||||
-rw-r--r-- | net/sched/sch_fifo.c | 34 |
2 files changed, 35 insertions, 0 deletions
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 75fd1c672c61..6cd491013b50 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -1707,6 +1707,7 @@ static int __init pktsched_init(void) | |||
1707 | { | 1707 | { |
1708 | register_qdisc(&pfifo_qdisc_ops); | 1708 | register_qdisc(&pfifo_qdisc_ops); |
1709 | register_qdisc(&bfifo_qdisc_ops); | 1709 | register_qdisc(&bfifo_qdisc_ops); |
1710 | register_qdisc(&pfifo_head_drop_qdisc_ops); | ||
1710 | register_qdisc(&mq_qdisc_ops); | 1711 | register_qdisc(&mq_qdisc_ops); |
1711 | proc_net_fops_create(&init_net, "psched", 0, &psched_fops); | 1712 | proc_net_fops_create(&init_net, "psched", 0, &psched_fops); |
1712 | 1713 | ||
diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c index 69188e8358b4..4b0a6cc44c77 100644 --- a/net/sched/sch_fifo.c +++ b/net/sched/sch_fifo.c | |||
@@ -43,6 +43,26 @@ static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch) | |||
43 | return qdisc_reshape_fail(skb, sch); | 43 | return qdisc_reshape_fail(skb, sch); |
44 | } | 44 | } |
45 | 45 | ||
46 | static int pfifo_tail_enqueue(struct sk_buff *skb, struct Qdisc* sch) | ||
47 | { | ||
48 | struct sk_buff *skb_head; | ||
49 | struct fifo_sched_data *q = qdisc_priv(sch); | ||
50 | |||
51 | if (likely(skb_queue_len(&sch->q) < q->limit)) | ||
52 | return qdisc_enqueue_tail(skb, sch); | ||
53 | |||
54 | /* queue full, remove one skb to fulfill the limit */ | ||
55 | skb_head = qdisc_dequeue_head(sch); | ||
56 | sch->bstats.bytes -= qdisc_pkt_len(skb_head); | ||
57 | sch->bstats.packets--; | ||
58 | sch->qstats.drops++; | ||
59 | kfree_skb(skb_head); | ||
60 | |||
61 | qdisc_enqueue_tail(skb, sch); | ||
62 | |||
63 | return NET_XMIT_CN; | ||
64 | } | ||
65 | |||
46 | static int fifo_init(struct Qdisc *sch, struct nlattr *opt) | 66 | static int fifo_init(struct Qdisc *sch, struct nlattr *opt) |
47 | { | 67 | { |
48 | struct fifo_sched_data *q = qdisc_priv(sch); | 68 | struct fifo_sched_data *q = qdisc_priv(sch); |
@@ -108,6 +128,20 @@ struct Qdisc_ops bfifo_qdisc_ops __read_mostly = { | |||
108 | }; | 128 | }; |
109 | EXPORT_SYMBOL(bfifo_qdisc_ops); | 129 | EXPORT_SYMBOL(bfifo_qdisc_ops); |
110 | 130 | ||
131 | struct Qdisc_ops pfifo_head_drop_qdisc_ops __read_mostly = { | ||
132 | .id = "pfifo_head_drop", | ||
133 | .priv_size = sizeof(struct fifo_sched_data), | ||
134 | .enqueue = pfifo_tail_enqueue, | ||
135 | .dequeue = qdisc_dequeue_head, | ||
136 | .peek = qdisc_peek_head, | ||
137 | .drop = qdisc_queue_drop_head, | ||
138 | .init = fifo_init, | ||
139 | .reset = qdisc_reset_queue, | ||
140 | .change = fifo_init, | ||
141 | .dump = fifo_dump, | ||
142 | .owner = THIS_MODULE, | ||
143 | }; | ||
144 | |||
111 | /* Pass size change message down to embedded FIFO */ | 145 | /* Pass size change message down to embedded FIFO */ |
112 | int fifo_set_limit(struct Qdisc *q, unsigned int limit) | 146 | int fifo_set_limit(struct Qdisc *q, unsigned int limit) |
113 | { | 147 | { |