diff options
author | Patrick McHardy <kaber@trash.net> | 2008-07-06 08:21:31 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-07-06 08:21:31 +0200 |
commit | 6fe1c7a5556807e9d7154a2d2fb938d8a9e47e5f (patch) | |
tree | 27758ea169b402aba70ef68bde8e554e7f135031 /include/net/sch_generic.h | |
parent | Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/ne... (diff) | |
download | linux-6fe1c7a5556807e9d7154a2d2fb938d8a9e47e5f.tar.xz linux-6fe1c7a5556807e9d7154a2d2fb938d8a9e47e5f.zip |
net-sched: add dynamically sized qdisc class hash helpers
Currently all qdiscs which allow to create classes uses a fixed sized hash
table with size 16 to hash the classes. This causes a large bottleneck
when using thousands of classes and unbound filters.
Add helpers for dynamically sized class hashes to fix this. The following
patches will convert the qdiscs to use them.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net/sch_generic.h')
-rw-r--r-- | include/net/sch_generic.h | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index a87fc0312edc..073f2580b83b 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -167,6 +167,48 @@ extern void qdisc_unlock_tree(struct net_device *dev); extern struct Qdisc noop_qdisc; extern struct Qdisc_ops noop_qdisc_ops; +struct Qdisc_class_common +{ + u32 classid; + struct hlist_node hnode; +}; + +struct Qdisc_class_hash +{ + struct hlist_head *hash; + unsigned int hashsize; + unsigned int hashmask; + unsigned int hashelems; +}; + +static inline unsigned int qdisc_class_hash(u32 id, u32 mask) +{ + id ^= id >> 8; + id ^= id >> 4; + return id & mask; +} + +static inline struct Qdisc_class_common * +qdisc_class_find(struct Qdisc_class_hash *hash, u32 id) +{ + struct Qdisc_class_common *cl; + struct hlist_node *n; + unsigned int h; + + h = qdisc_class_hash(id, hash->hashmask); + hlist_for_each_entry(cl, n, &hash->hash[h], hnode) { + if (cl->classid == id) + return cl; + } + return NULL; +} + +extern int qdisc_class_hash_init(struct Qdisc_class_hash *); +extern void qdisc_class_hash_insert(struct Qdisc_class_hash *, struct Qdisc_class_common *); +extern void qdisc_class_hash_remove(struct Qdisc_class_hash *, struct Qdisc_class_common *); +extern void qdisc_class_hash_grow(struct Qdisc *, struct Qdisc_class_hash *); +extern void qdisc_class_hash_destroy(struct Qdisc_class_hash *); + extern void dev_init_scheduler(struct net_device *dev); extern void dev_shutdown(struct net_device *dev); extern void dev_activate(struct net_device *dev); |