diff options
Diffstat (limited to 'net/sched/sch_fifo.c')
-rw-r--r-- | net/sched/sch_fifo.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c index 69188e8358b4..5948bafa8ce2 100644 --- a/net/sched/sch_fifo.c +++ b/net/sched/sch_fifo.c | |||
@@ -10,6 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/slab.h> | ||
13 | #include <linux/types.h> | 14 | #include <linux/types.h> |
14 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
15 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
@@ -43,6 +44,26 @@ static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch) | |||
43 | return qdisc_reshape_fail(skb, sch); | 44 | return qdisc_reshape_fail(skb, sch); |
44 | } | 45 | } |
45 | 46 | ||
47 | static int pfifo_tail_enqueue(struct sk_buff *skb, struct Qdisc* sch) | ||
48 | { | ||
49 | struct sk_buff *skb_head; | ||
50 | struct fifo_sched_data *q = qdisc_priv(sch); | ||
51 | |||
52 | if (likely(skb_queue_len(&sch->q) < q->limit)) | ||
53 | return qdisc_enqueue_tail(skb, sch); | ||
54 | |||
55 | /* queue full, remove one skb to fulfill the limit */ | ||
56 | skb_head = qdisc_dequeue_head(sch); | ||
57 | sch->bstats.bytes -= qdisc_pkt_len(skb_head); | ||
58 | sch->bstats.packets--; | ||
59 | sch->qstats.drops++; | ||
60 | kfree_skb(skb_head); | ||
61 | |||
62 | qdisc_enqueue_tail(skb, sch); | ||
63 | |||
64 | return NET_XMIT_CN; | ||
65 | } | ||
66 | |||
46 | static int fifo_init(struct Qdisc *sch, struct nlattr *opt) | 67 | static int fifo_init(struct Qdisc *sch, struct nlattr *opt) |
47 | { | 68 | { |
48 | struct fifo_sched_data *q = qdisc_priv(sch); | 69 | struct fifo_sched_data *q = qdisc_priv(sch); |
@@ -108,6 +129,20 @@ struct Qdisc_ops bfifo_qdisc_ops __read_mostly = { | |||
108 | }; | 129 | }; |
109 | EXPORT_SYMBOL(bfifo_qdisc_ops); | 130 | EXPORT_SYMBOL(bfifo_qdisc_ops); |
110 | 131 | ||
132 | struct Qdisc_ops pfifo_head_drop_qdisc_ops __read_mostly = { | ||
133 | .id = "pfifo_head_drop", | ||
134 | .priv_size = sizeof(struct fifo_sched_data), | ||
135 | .enqueue = pfifo_tail_enqueue, | ||
136 | .dequeue = qdisc_dequeue_head, | ||
137 | .peek = qdisc_peek_head, | ||
138 | .drop = qdisc_queue_drop_head, | ||
139 | .init = fifo_init, | ||
140 | .reset = qdisc_reset_queue, | ||
141 | .change = fifo_init, | ||
142 | .dump = fifo_dump, | ||
143 | .owner = THIS_MODULE, | ||
144 | }; | ||
145 | |||
111 | /* Pass size change message down to embedded FIFO */ | 146 | /* Pass size change message down to embedded FIFO */ |
112 | int fifo_set_limit(struct Qdisc *q, unsigned int limit) | 147 | int fifo_set_limit(struct Qdisc *q, unsigned int limit) |
113 | { | 148 | { |