aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2005-04-24 23:19:54 -0400
committerDavid S. Miller <davem@davemloft.net>2005-04-24 23:19:54 -0400
commitc5c13fafd6548fe36b8fe9285c1912fcf96379f4 (patch)
tree892a1f3c6fa74e2b75c2278c44b58a8813f770cc
parent0d3d077cd4f1154e63a9858e47fe3fb1ad0c03e5 (diff)
[PKT_SCHED]: improve hashing performance of cls_fw
Calculate hashtable size to fit into a page instead of a hardcoded 256 buckets hash table. Results in a 1024 buckets hashtable on most systems. Replace old naive extract-8-lsb-bits algorithm with a better algorithm xor'ing 3 or 4 bit fields at the size of the hashtable array index in order to improve distribution if the majority of the lower bits are unused while keeping zero collision behaviour for the most common use case. Thanks to Wang Jian <lark@linux.net.cn> for bringing this issue to attention and to Eran Mann <emann@mrv.com> for the initial idea for this new algorithm. Signed-off-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/sched/cls_fw.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index fdfc83af3d1f..29d8b9a4d162 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -46,9 +46,11 @@
46#include <net/act_api.h> 46#include <net/act_api.h>
47#include <net/pkt_cls.h> 47#include <net/pkt_cls.h>
48 48
49#define HTSIZE (PAGE_SIZE/sizeof(struct fw_filter *))
50
49struct fw_head 51struct fw_head
50{ 52{
51 struct fw_filter *ht[256]; 53 struct fw_filter *ht[HTSIZE];
52}; 54};
53 55
54struct fw_filter 56struct fw_filter
@@ -69,7 +71,28 @@ static struct tcf_ext_map fw_ext_map = {
69 71
70static __inline__ int fw_hash(u32 handle) 72static __inline__ int fw_hash(u32 handle)
71{ 73{
72 return handle&0xFF; 74 if (HTSIZE == 4096)
75 return ((handle >> 24) & 0xFFF) ^
76 ((handle >> 12) & 0xFFF) ^
77 (handle & 0xFFF);
78 else if (HTSIZE == 2048)
79 return ((handle >> 22) & 0x7FF) ^
80 ((handle >> 11) & 0x7FF) ^
81 (handle & 0x7FF);
82 else if (HTSIZE == 1024)
83 return ((handle >> 20) & 0x3FF) ^
84 ((handle >> 10) & 0x3FF) ^
85 (handle & 0x3FF);
86 else if (HTSIZE == 512)
87 return (handle >> 27) ^
88 ((handle >> 18) & 0x1FF) ^
89 ((handle >> 9) & 0x1FF) ^
90 (handle & 0x1FF);
91 else if (HTSIZE == 256) {
92 u8 *t = (u8 *) &handle;
93 return t[0] ^ t[1] ^ t[2] ^ t[3];
94 } else
95 return handle & (HTSIZE - 1);
73} 96}
74 97
75static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp, 98static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp,
@@ -152,7 +175,7 @@ static void fw_destroy(struct tcf_proto *tp)
152 if (head == NULL) 175 if (head == NULL)
153 return; 176 return;
154 177
155 for (h=0; h<256; h++) { 178 for (h=0; h<HTSIZE; h++) {
156 while ((f=head->ht[h]) != NULL) { 179 while ((f=head->ht[h]) != NULL) {
157 head->ht[h] = f->next; 180 head->ht[h] = f->next;
158 fw_delete_filter(tp, f); 181 fw_delete_filter(tp, f);
@@ -291,7 +314,7 @@ static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg)
291 if (arg->stop) 314 if (arg->stop)
292 return; 315 return;
293 316
294 for (h = 0; h < 256; h++) { 317 for (h = 0; h < HTSIZE; h++) {
295 struct fw_filter *f; 318 struct fw_filter *f;
296 319
297 for (f = head->ht[h]; f; f = f->next) { 320 for (f = head->ht[h]; f; f = f->next) {