diff options
-rw-r--r-- | include/net/pkt_sched.h | 4 | ||||
-rw-r--r-- | net/sched/sch_fifo.c | 42 | ||||
-rw-r--r-- | net/sched/sch_netem.c | 24 | ||||
-rw-r--r-- | net/sched/sch_red.c | 33 | ||||
-rw-r--r-- | net/sched/sch_tbf.c | 33 |
5 files changed, 54 insertions, 82 deletions
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index 46fb4d80c74a..8e3a0c4e9d97 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h | |||
@@ -72,6 +72,10 @@ extern void qdisc_watchdog_cancel(struct qdisc_watchdog *wd); | |||
72 | extern struct Qdisc_ops pfifo_qdisc_ops; | 72 | extern struct Qdisc_ops pfifo_qdisc_ops; |
73 | extern struct Qdisc_ops bfifo_qdisc_ops; | 73 | extern struct Qdisc_ops bfifo_qdisc_ops; |
74 | 74 | ||
75 | extern int fifo_set_limit(struct Qdisc *q, unsigned int limit); | ||
76 | extern struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops, | ||
77 | unsigned int limit); | ||
78 | |||
75 | extern int register_qdisc(struct Qdisc_ops *qops); | 79 | extern int register_qdisc(struct Qdisc_ops *qops); |
76 | extern int unregister_qdisc(struct Qdisc_ops *qops); | 80 | extern int unregister_qdisc(struct Qdisc_ops *qops); |
77 | extern struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle); | 81 | extern struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle); |
diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c index 95ed48221652..82d7d7bbbb16 100644 --- a/net/sched/sch_fifo.c +++ b/net/sched/sch_fifo.c | |||
@@ -107,3 +107,45 @@ struct Qdisc_ops bfifo_qdisc_ops __read_mostly = { | |||
107 | .owner = THIS_MODULE, | 107 | .owner = THIS_MODULE, |
108 | }; | 108 | }; |
109 | EXPORT_SYMBOL(bfifo_qdisc_ops); | 109 | EXPORT_SYMBOL(bfifo_qdisc_ops); |
110 | |||
111 | /* Pass size change message down to embedded FIFO */ | ||
112 | int fifo_set_limit(struct Qdisc *q, unsigned int limit) | ||
113 | { | ||
114 | struct nlattr *nla; | ||
115 | int ret = -ENOMEM; | ||
116 | |||
117 | /* Hack to avoid sending change message to non-FIFO */ | ||
118 | if (strncmp(q->ops->id + 1, "fifo", 4) != 0) | ||
119 | return 0; | ||
120 | |||
121 | nla = kmalloc(nla_attr_size(sizeof(struct tc_fifo_qopt)), GFP_KERNEL); | ||
122 | if (nla) { | ||
123 | nla->nla_type = RTM_NEWQDISC; | ||
124 | nla->nla_len = nla_attr_size(sizeof(struct tc_fifo_qopt)); | ||
125 | ((struct tc_fifo_qopt *)nla_data(nla))->limit = limit; | ||
126 | |||
127 | ret = q->ops->change(q, nla); | ||
128 | kfree(nla); | ||
129 | } | ||
130 | return ret; | ||
131 | } | ||
132 | EXPORT_SYMBOL(fifo_set_limit); | ||
133 | |||
134 | struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops, | ||
135 | unsigned int limit) | ||
136 | { | ||
137 | struct Qdisc *q; | ||
138 | int err = -ENOMEM; | ||
139 | |||
140 | q = qdisc_create_dflt(sch->dev, ops, TC_H_MAKE(sch->handle, 1)); | ||
141 | if (q) { | ||
142 | err = fifo_set_limit(q, limit); | ||
143 | if (err < 0) { | ||
144 | qdisc_destroy(q); | ||
145 | q = NULL; | ||
146 | } | ||
147 | } | ||
148 | |||
149 | return q ? : ERR_PTR(err); | ||
150 | } | ||
151 | EXPORT_SYMBOL(fifo_create_dflt); | ||
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index c9c649b26eaa..24697667247c 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c | |||
@@ -310,28 +310,6 @@ static void netem_reset(struct Qdisc *sch) | |||
310 | qdisc_watchdog_cancel(&q->watchdog); | 310 | qdisc_watchdog_cancel(&q->watchdog); |
311 | } | 311 | } |
312 | 312 | ||
313 | /* Pass size change message down to embedded FIFO */ | ||
314 | static int set_fifo_limit(struct Qdisc *q, int limit) | ||
315 | { | ||
316 | struct nlattr *nla; | ||
317 | int ret = -ENOMEM; | ||
318 | |||
319 | /* Hack to avoid sending change message to non-FIFO */ | ||
320 | if (strncmp(q->ops->id + 1, "fifo", 4) != 0) | ||
321 | return 0; | ||
322 | |||
323 | nla = kmalloc(nla_attr_size(sizeof(struct tc_fifo_qopt)), GFP_KERNEL); | ||
324 | if (nla) { | ||
325 | nla->nla_type = RTM_NEWQDISC; | ||
326 | nla->nla_len = nla_attr_size(sizeof(struct tc_fifo_qopt)); | ||
327 | ((struct tc_fifo_qopt *)nla_data(nla))->limit = limit; | ||
328 | |||
329 | ret = q->ops->change(q, nla); | ||
330 | kfree(nla); | ||
331 | } | ||
332 | return ret; | ||
333 | } | ||
334 | |||
335 | /* | 313 | /* |
336 | * Distribution data is a variable size payload containing | 314 | * Distribution data is a variable size payload containing |
337 | * signed 16 bit values. | 315 | * signed 16 bit values. |
@@ -416,7 +394,7 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt) | |||
416 | if (ret < 0) | 394 | if (ret < 0) |
417 | return ret; | 395 | return ret; |
418 | 396 | ||
419 | ret = set_fifo_limit(q->qdisc, qopt->limit); | 397 | ret = fifo_set_limit(q->qdisc, qopt->limit); |
420 | if (ret) { | 398 | if (ret) { |
421 | pr_debug("netem: can't set fifo limit\n"); | 399 | pr_debug("netem: can't set fifo limit\n"); |
422 | return ret; | 400 | return ret; |
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 5c569853b9c0..77098acf0adc 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c | |||
@@ -174,33 +174,6 @@ static void red_destroy(struct Qdisc *sch) | |||
174 | qdisc_destroy(q->qdisc); | 174 | qdisc_destroy(q->qdisc); |
175 | } | 175 | } |
176 | 176 | ||
177 | static struct Qdisc *red_create_dflt(struct Qdisc *sch, u32 limit) | ||
178 | { | ||
179 | struct Qdisc *q; | ||
180 | struct nlattr *nla; | ||
181 | int ret; | ||
182 | |||
183 | q = qdisc_create_dflt(sch->dev, &bfifo_qdisc_ops, | ||
184 | TC_H_MAKE(sch->handle, 1)); | ||
185 | if (q) { | ||
186 | nla = kmalloc(nla_attr_size(sizeof(struct tc_fifo_qopt)), | ||
187 | GFP_KERNEL); | ||
188 | if (nla) { | ||
189 | nla->nla_type = RTM_NEWQDISC; | ||
190 | nla->nla_len = nla_attr_size(sizeof(struct tc_fifo_qopt)); | ||
191 | ((struct tc_fifo_qopt *)nla_data(nla))->limit = limit; | ||
192 | |||
193 | ret = q->ops->change(q, nla); | ||
194 | kfree(nla); | ||
195 | |||
196 | if (ret == 0) | ||
197 | return q; | ||
198 | } | ||
199 | qdisc_destroy(q); | ||
200 | } | ||
201 | return NULL; | ||
202 | } | ||
203 | |||
204 | static const struct nla_policy red_policy[TCA_RED_MAX + 1] = { | 177 | static const struct nla_policy red_policy[TCA_RED_MAX + 1] = { |
205 | [TCA_RED_PARMS] = { .len = sizeof(struct tc_red_qopt) }, | 178 | [TCA_RED_PARMS] = { .len = sizeof(struct tc_red_qopt) }, |
206 | [TCA_RED_STAB] = { .len = RED_STAB_SIZE }, | 179 | [TCA_RED_STAB] = { .len = RED_STAB_SIZE }, |
@@ -228,9 +201,9 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt) | |||
228 | ctl = nla_data(tb[TCA_RED_PARMS]); | 201 | ctl = nla_data(tb[TCA_RED_PARMS]); |
229 | 202 | ||
230 | if (ctl->limit > 0) { | 203 | if (ctl->limit > 0) { |
231 | child = red_create_dflt(sch, ctl->limit); | 204 | child = fifo_create_dflt(sch, &bfifo_qdisc_ops, ctl->limit); |
232 | if (child == NULL) | 205 | if (IS_ERR(child)) |
233 | return -ENOMEM; | 206 | return PTR_ERR(child); |
234 | } | 207 | } |
235 | 208 | ||
236 | sch_tree_lock(sch); | 209 | sch_tree_lock(sch); |
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 0b7d78f59d8c..444c227fcb6b 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c | |||
@@ -242,34 +242,6 @@ static void tbf_reset(struct Qdisc* sch) | |||
242 | qdisc_watchdog_cancel(&q->watchdog); | 242 | qdisc_watchdog_cancel(&q->watchdog); |
243 | } | 243 | } |
244 | 244 | ||
245 | static struct Qdisc *tbf_create_dflt_qdisc(struct Qdisc *sch, u32 limit) | ||
246 | { | ||
247 | struct Qdisc *q; | ||
248 | struct nlattr *nla; | ||
249 | int ret; | ||
250 | |||
251 | q = qdisc_create_dflt(sch->dev, &bfifo_qdisc_ops, | ||
252 | TC_H_MAKE(sch->handle, 1)); | ||
253 | if (q) { | ||
254 | nla = kmalloc(nla_attr_size(sizeof(struct tc_fifo_qopt)), | ||
255 | GFP_KERNEL); | ||
256 | if (nla) { | ||
257 | nla->nla_type = RTM_NEWQDISC; | ||
258 | nla->nla_len = nla_attr_size(sizeof(struct tc_fifo_qopt)); | ||
259 | ((struct tc_fifo_qopt *)nla_data(nla))->limit = limit; | ||
260 | |||
261 | ret = q->ops->change(q, nla); | ||
262 | kfree(nla); | ||
263 | |||
264 | if (ret == 0) | ||
265 | return q; | ||
266 | } | ||
267 | qdisc_destroy(q); | ||
268 | } | ||
269 | |||
270 | return NULL; | ||
271 | } | ||
272 | |||
273 | static const struct nla_policy tbf_policy[TCA_TBF_MAX + 1] = { | 245 | static const struct nla_policy tbf_policy[TCA_TBF_MAX + 1] = { |
274 | [TCA_TBF_PARMS] = { .len = sizeof(struct tc_tbf_qopt) }, | 246 | [TCA_TBF_PARMS] = { .len = sizeof(struct tc_tbf_qopt) }, |
275 | [TCA_TBF_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, | 247 | [TCA_TBF_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, |
@@ -322,8 +294,11 @@ static int tbf_change(struct Qdisc* sch, struct nlattr *opt) | |||
322 | goto done; | 294 | goto done; |
323 | 295 | ||
324 | if (qopt->limit > 0) { | 296 | if (qopt->limit > 0) { |
325 | if ((child = tbf_create_dflt_qdisc(sch, qopt->limit)) == NULL) | 297 | child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit); |
298 | if (IS_ERR(child)) { | ||
299 | err = PTR_ERR(child); | ||
326 | goto done; | 300 | goto done; |
301 | } | ||
327 | } | 302 | } |
328 | 303 | ||
329 | sch_tree_lock(sch); | 304 | sch_tree_lock(sch); |