From 66c6f529c31e2886536aad4b2320d566deb1f150 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 18:07:51 -0800 Subject: [NET]: net/sched annotations. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/sched/sch_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/sched/sch_api.c') diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 0b648929114..d99802f3023 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -1112,7 +1112,7 @@ int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_result *res) { int err = 0; - u32 protocol = skb->protocol; + __be16 protocol = skb->protocol; #ifdef CONFIG_NET_CLS_ACT struct tcf_proto *otp = tp; reclassify: -- cgit v1.2.3-70-g09d2 From 43effa1e57fc4635e0301b27d78f9d83afe78974 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 17:35:48 -0800 Subject: [NET_SCHED]: Fix endless loops caused by inaccurate qlen counters (part 1) There are multiple problems related to qlen adjustment that can lead to an upper qdisc getting out of sync with the real number of packets queued, leading to endless dequeueing attempts by the upper layer code. All qdiscs must maintain an accurate q.qlen counter. There are basically two groups of operations affecting the qlen: operations that propagate down the tree (enqueue, dequeue, requeue, drop, reset) beginning at the root qdisc and operations only affecting a subtree or single qdisc (change, graft, delete class). Since qlen changes during operations from the second group don't propagate to ancestor qdiscs, their qlen values become desynchronized. This patch adds a function to propagate qlen changes up the qdisc tree, optionally calling a callback function to perform qdisc-internal maintenance when the child qdisc becomes empty. The follow-up patches will convert all qdiscs to use this function where necessary. Noticed by Timo Steinbach . Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/sch_generic.h | 2 ++ net/sched/sch_api.c | 38 ++++++++++++++++++++++++++++++++------ 2 files changed, 34 insertions(+), 6 deletions(-) (limited to 'net/sched/sch_api.c') diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index b37572db12a..82086392735 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -60,6 +60,7 @@ struct Qdisc_class_ops int (*graft)(struct Qdisc *, unsigned long cl, struct Qdisc *, struct Qdisc **); struct Qdisc * (*leaf)(struct Qdisc *, unsigned long cl); + void (*qlen_notify)(struct Qdisc *, unsigned long); /* Class manipulation routines */ unsigned long (*get)(struct Qdisc *, u32 classid); @@ -172,6 +173,7 @@ extern void dev_activate(struct net_device *dev); extern void dev_deactivate(struct net_device *dev); extern void qdisc_reset(struct Qdisc *qdisc); extern void qdisc_destroy(struct Qdisc *qdisc); +extern void qdisc_tree_decrease_qlen(struct Qdisc *qdisc, unsigned int n); extern struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops); extern struct Qdisc *qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops, u32 parentid); diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index d99802f3023..05a93da6f05 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -191,21 +191,27 @@ int unregister_qdisc(struct Qdisc_ops *qops) (root qdisc, all its children, children of children etc.) */ -struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) +static struct Qdisc *__qdisc_lookup(struct net_device *dev, u32 handle) { struct Qdisc *q; - read_lock(&qdisc_tree_lock); list_for_each_entry(q, &dev->qdisc_list, list) { - if (q->handle == handle) { - read_unlock(&qdisc_tree_lock); + if (q->handle == handle) return q; - } } - read_unlock(&qdisc_tree_lock); return NULL; } +struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) +{ + struct Qdisc *q; + + read_lock(&qdisc_tree_lock); + q = __qdisc_lookup(dev, handle); + read_unlock(&qdisc_tree_lock); + return q; +} + static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid) { unsigned long cl; @@ -348,6 +354,26 @@ dev_graft_qdisc(struct net_device *dev, struct Qdisc *qdisc) return oqdisc; } +void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n) +{ + struct Qdisc_class_ops *cops; + unsigned long cl; + u32 parentid; + + if (n == 0) + return; + while ((parentid = sch->parent)) { + sch = __qdisc_lookup(sch->dev, TC_H_MAJ(parentid)); + cops = sch->ops->cl_ops; + if (cops->qlen_notify) { + cl = cops->get(sch, parentid); + cops->qlen_notify(sch, cl); + cops->put(sch, cl); + } + sch->q.qlen -= n; + } +} +EXPORT_SYMBOL(qdisc_tree_decrease_qlen); /* Graft qdisc "new" to class "classid" of qdisc "parent" or to device "dev". -- cgit v1.2.3-70-g09d2 From 5f68e4c07c7b97a5b06f0b5e313528d36415a60d Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 30 Nov 2006 19:50:36 -0800 Subject: [PKT_SCHED]: Remove unused exports. This patch removes the following unused EXPORT_SYMBOL's: - sch_api.c: qdisc_lookup - sch_generic.c: __netdev_watchdog_up - sch_generic.c: noop_qdisc_ops - sch_generic.c: qdisc_alloc Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller --- net/sched/sch_api.c | 1 - net/sched/sch_generic.c | 3 --- 2 files changed, 4 deletions(-) (limited to 'net/sched/sch_api.c') diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 05a93da6f05..65825f4409d 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -1303,7 +1303,6 @@ static int __init pktsched_init(void) subsys_initcall(pktsched_init); -EXPORT_SYMBOL(qdisc_lookup); EXPORT_SYMBOL(qdisc_get_rtab); EXPORT_SYMBOL(qdisc_put_rtab); EXPORT_SYMBOL(register_qdisc); diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index deafeb9cb70..bc116bd6937 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -609,13 +609,10 @@ void dev_shutdown(struct net_device *dev) qdisc_unlock_tree(dev); } -EXPORT_SYMBOL(__netdev_watchdog_up); EXPORT_SYMBOL(netif_carrier_on); EXPORT_SYMBOL(netif_carrier_off); EXPORT_SYMBOL(noop_qdisc); -EXPORT_SYMBOL(noop_qdisc_ops); EXPORT_SYMBOL(qdisc_create_dflt); -EXPORT_SYMBOL(qdisc_alloc); EXPORT_SYMBOL(qdisc_destroy); EXPORT_SYMBOL(qdisc_reset); EXPORT_SYMBOL(qdisc_lock_tree); -- cgit v1.2.3-70-g09d2