aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/pkt_sched.h4
-rw-r--r--net/sched/sch_fifo.c42
-rw-r--r--net/sched/sch_netem.c24
-rw-r--r--net/sched/sch_red.c33
-rw-r--r--net/sched/sch_tbf.c33
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);
72extern struct Qdisc_ops pfifo_qdisc_ops; 72extern struct Qdisc_ops pfifo_qdisc_ops;
73extern struct Qdisc_ops bfifo_qdisc_ops; 73extern struct Qdisc_ops bfifo_qdisc_ops;
74 74
75extern int fifo_set_limit(struct Qdisc *q, unsigned int limit);
76extern struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops,
77 unsigned int limit);
78
75extern int register_qdisc(struct Qdisc_ops *qops); 79extern int register_qdisc(struct Qdisc_ops *qops);
76extern int unregister_qdisc(struct Qdisc_ops *qops); 80extern int unregister_qdisc(struct Qdisc_ops *qops);
77extern struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle); 81extern 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};
109EXPORT_SYMBOL(bfifo_qdisc_ops); 109EXPORT_SYMBOL(bfifo_qdisc_ops);
110
111/* Pass size change message down to embedded FIFO */
112int 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}
132EXPORT_SYMBOL(fifo_set_limit);
133
134struct 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}
151EXPORT_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 */
314static 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
177static 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
204static const struct nla_policy red_policy[TCA_RED_MAX + 1] = { 177static 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
245static 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
273static const struct nla_policy tbf_policy[TCA_TBF_MAX + 1] = { 245static 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);