Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * net/sched/sch_fifo.c The simplest FIFO queue. | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or | |
5 | * modify it under the terms of the GNU General Public License | |
6 | * as published by the Free Software Foundation; either version | |
7 | * 2 of the License, or (at your option) any later version. | |
8 | * | |
9 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | |
10 | */ | |
11 | ||
12 | #include <linux/config.h> | |
13 | #include <linux/module.h> | |
14 | #include <asm/uaccess.h> | |
15 | #include <asm/system.h> | |
16 | #include <linux/bitops.h> | |
17 | #include <linux/types.h> | |
18 | #include <linux/kernel.h> | |
19 | #include <linux/sched.h> | |
20 | #include <linux/string.h> | |
21 | #include <linux/mm.h> | |
22 | #include <linux/socket.h> | |
23 | #include <linux/sockios.h> | |
24 | #include <linux/in.h> | |
25 | #include <linux/errno.h> | |
26 | #include <linux/interrupt.h> | |
27 | #include <linux/if_ether.h> | |
28 | #include <linux/inet.h> | |
29 | #include <linux/netdevice.h> | |
30 | #include <linux/etherdevice.h> | |
31 | #include <linux/notifier.h> | |
32 | #include <net/ip.h> | |
33 | #include <net/route.h> | |
34 | #include <linux/skbuff.h> | |
35 | #include <net/sock.h> | |
36 | #include <net/pkt_sched.h> | |
37 | ||
38 | /* 1 band FIFO pseudo-"scheduler" */ | |
39 | ||
40 | struct fifo_sched_data | |
41 | { | |
42 | unsigned limit; | |
43 | }; | |
44 | ||
45 | static int | |
46 | bfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch) | |
47 | { | |
48 | struct fifo_sched_data *q = qdisc_priv(sch); | |
49 | ||
aaae3013 TG |
50 | if (likely(sch->qstats.backlog + skb->len <= q->limit)) |
51 | return qdisc_enqueue_tail(skb, sch); | |
1da177e4 | 52 | |
aaae3013 | 53 | return qdisc_reshape_fail(skb, sch); |
1da177e4 LT |
54 | } |
55 | ||
56 | static int | |
57 | pfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch) | |
58 | { | |
59 | struct fifo_sched_data *q = qdisc_priv(sch); | |
60 | ||
aaae3013 TG |
61 | if (likely(skb_queue_len(&sch->q) < q->limit)) |
62 | return qdisc_enqueue_tail(skb, sch); | |
1da177e4 | 63 | |
aaae3013 | 64 | return qdisc_reshape_fail(skb, sch); |
1da177e4 LT |
65 | } |
66 | ||
67 | static int fifo_init(struct Qdisc *sch, struct rtattr *opt) | |
68 | { | |
69 | struct fifo_sched_data *q = qdisc_priv(sch); | |
70 | ||
71 | if (opt == NULL) { | |
72 | unsigned int limit = sch->dev->tx_queue_len ? : 1; | |
73 | ||
74 | if (sch->ops == &bfifo_qdisc_ops) | |
75 | q->limit = limit*sch->dev->mtu; | |
76 | else | |
77 | q->limit = limit; | |
78 | } else { | |
79 | struct tc_fifo_qopt *ctl = RTA_DATA(opt); | |
80 | if (opt->rta_len < RTA_LENGTH(sizeof(*ctl))) | |
81 | return -EINVAL; | |
82 | q->limit = ctl->limit; | |
83 | } | |
84 | return 0; | |
85 | } | |
86 | ||
87 | static int fifo_dump(struct Qdisc *sch, struct sk_buff *skb) | |
88 | { | |
89 | struct fifo_sched_data *q = qdisc_priv(sch); | |
90 | unsigned char *b = skb->tail; | |
91 | struct tc_fifo_qopt opt; | |
92 | ||
93 | opt.limit = q->limit; | |
94 | RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); | |
95 | ||
96 | return skb->len; | |
97 | ||
98 | rtattr_failure: | |
99 | skb_trim(skb, b - skb->data); | |
100 | return -1; | |
101 | } | |
102 | ||
103 | struct Qdisc_ops pfifo_qdisc_ops = { | |
104 | .next = NULL, | |
105 | .cl_ops = NULL, | |
106 | .id = "pfifo", | |
107 | .priv_size = sizeof(struct fifo_sched_data), | |
108 | .enqueue = pfifo_enqueue, | |
aaae3013 TG |
109 | .dequeue = qdisc_dequeue_head, |
110 | .requeue = qdisc_requeue, | |
111 | .drop = qdisc_queue_drop, | |
1da177e4 | 112 | .init = fifo_init, |
aaae3013 | 113 | .reset = qdisc_reset_queue, |
1da177e4 LT |
114 | .destroy = NULL, |
115 | .change = fifo_init, | |
116 | .dump = fifo_dump, | |
117 | .owner = THIS_MODULE, | |
118 | }; | |
119 | ||
120 | struct Qdisc_ops bfifo_qdisc_ops = { | |
121 | .next = NULL, | |
122 | .cl_ops = NULL, | |
123 | .id = "bfifo", | |
124 | .priv_size = sizeof(struct fifo_sched_data), | |
125 | .enqueue = bfifo_enqueue, | |
aaae3013 TG |
126 | .dequeue = qdisc_dequeue_head, |
127 | .requeue = qdisc_requeue, | |
128 | .drop = qdisc_queue_drop, | |
1da177e4 | 129 | .init = fifo_init, |
aaae3013 | 130 | .reset = qdisc_reset_queue, |
1da177e4 LT |
131 | .destroy = NULL, |
132 | .change = fifo_init, | |
133 | .dump = fifo_dump, | |
134 | .owner = THIS_MODULE, | |
135 | }; | |
136 | ||
137 | EXPORT_SYMBOL(bfifo_qdisc_ops); | |
138 | EXPORT_SYMBOL(pfifo_qdisc_ops); |