aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/sch_generic.h2
-rw-r--r--net/sched/sch_api.c38
2 files changed, 34 insertions, 6 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index b37572db12ab..82086392735a 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -60,6 +60,7 @@ struct Qdisc_class_ops
60 int (*graft)(struct Qdisc *, unsigned long cl, 60 int (*graft)(struct Qdisc *, unsigned long cl,
61 struct Qdisc *, struct Qdisc **); 61 struct Qdisc *, struct Qdisc **);
62 struct Qdisc * (*leaf)(struct Qdisc *, unsigned long cl); 62 struct Qdisc * (*leaf)(struct Qdisc *, unsigned long cl);
63 void (*qlen_notify)(struct Qdisc *, unsigned long);
63 64
64 /* Class manipulation routines */ 65 /* Class manipulation routines */
65 unsigned long (*get)(struct Qdisc *, u32 classid); 66 unsigned long (*get)(struct Qdisc *, u32 classid);
@@ -172,6 +173,7 @@ extern void dev_activate(struct net_device *dev);
172extern void dev_deactivate(struct net_device *dev); 173extern void dev_deactivate(struct net_device *dev);
173extern void qdisc_reset(struct Qdisc *qdisc); 174extern void qdisc_reset(struct Qdisc *qdisc);
174extern void qdisc_destroy(struct Qdisc *qdisc); 175extern void qdisc_destroy(struct Qdisc *qdisc);
176extern void qdisc_tree_decrease_qlen(struct Qdisc *qdisc, unsigned int n);
175extern struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops); 177extern struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops);
176extern struct Qdisc *qdisc_create_dflt(struct net_device *dev, 178extern struct Qdisc *qdisc_create_dflt(struct net_device *dev,
177 struct Qdisc_ops *ops, u32 parentid); 179 struct Qdisc_ops *ops, u32 parentid);
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index d99802f3023d..05a93da6f057 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -191,21 +191,27 @@ int unregister_qdisc(struct Qdisc_ops *qops)
191 (root qdisc, all its children, children of children etc.) 191 (root qdisc, all its children, children of children etc.)
192 */ 192 */
193 193
194struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) 194static struct Qdisc *__qdisc_lookup(struct net_device *dev, u32 handle)
195{ 195{
196 struct Qdisc *q; 196 struct Qdisc *q;
197 197
198 read_lock(&qdisc_tree_lock);
199 list_for_each_entry(q, &dev->qdisc_list, list) { 198 list_for_each_entry(q, &dev->qdisc_list, list) {
200 if (q->handle == handle) { 199 if (q->handle == handle)
201 read_unlock(&qdisc_tree_lock);
202 return q; 200 return q;
203 }
204 } 201 }
205 read_unlock(&qdisc_tree_lock);
206 return NULL; 202 return NULL;
207} 203}
208 204
205struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
206{
207 struct Qdisc *q;
208
209 read_lock(&qdisc_tree_lock);
210 q = __qdisc_lookup(dev, handle);
211 read_unlock(&qdisc_tree_lock);
212 return q;
213}
214
209static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid) 215static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid)
210{ 216{
211 unsigned long cl; 217 unsigned long cl;
@@ -348,6 +354,26 @@ dev_graft_qdisc(struct net_device *dev, struct Qdisc *qdisc)
348 return oqdisc; 354 return oqdisc;
349} 355}
350 356
357void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n)
358{
359 struct Qdisc_class_ops *cops;
360 unsigned long cl;
361 u32 parentid;
362
363 if (n == 0)
364 return;
365 while ((parentid = sch->parent)) {
366 sch = __qdisc_lookup(sch->dev, TC_H_MAJ(parentid));
367 cops = sch->ops->cl_ops;
368 if (cops->qlen_notify) {
369 cl = cops->get(sch, parentid);
370 cops->qlen_notify(sch, cl);
371 cops->put(sch, cl);
372 }
373 sch->q.qlen -= n;
374 }
375}
376EXPORT_SYMBOL(qdisc_tree_decrease_qlen);
351 377
352/* Graft qdisc "new" to class "classid" of qdisc "parent" or 378/* Graft qdisc "new" to class "classid" of qdisc "parent" or
353 to device "dev". 379 to device "dev".