diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2006-08-24 07:50:50 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-09-22 18:08:49 -0400 |
commit | 44e36b42a8378be1dcf7e6f8a1cb2710a8903387 (patch) | |
tree | 2c057957a4e4dc7f679ac671a9f091f3fe366b92 /net/xfrm/xfrm_state.c | |
parent | 2518c7c2b3d7f0a6b302b4efe17c911f8dd4049f (diff) |
[XFRM]: Extract common hashing code into xfrm_hash.[ch]
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/xfrm/xfrm_state.c')
-rw-r--r-- | net/xfrm/xfrm_state.c | 128 |
1 files changed, 16 insertions, 112 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 37213f9f6a02..4341795eb244 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -18,11 +18,11 @@ | |||
18 | #include <linux/pfkeyv2.h> | 18 | #include <linux/pfkeyv2.h> |
19 | #include <linux/ipsec.h> | 19 | #include <linux/ipsec.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/bootmem.h> | ||
22 | #include <linux/vmalloc.h> | ||
23 | #include <linux/cache.h> | 21 | #include <linux/cache.h> |
24 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
25 | 23 | ||
24 | #include "xfrm_hash.h" | ||
25 | |||
26 | struct sock *xfrm_nl; | 26 | struct sock *xfrm_nl; |
27 | EXPORT_SYMBOL(xfrm_nl); | 27 | EXPORT_SYMBOL(xfrm_nl); |
28 | 28 | ||
@@ -55,44 +55,6 @@ static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024; | |||
55 | static unsigned int xfrm_state_num; | 55 | static unsigned int xfrm_state_num; |
56 | static unsigned int xfrm_state_genid; | 56 | static unsigned int xfrm_state_genid; |
57 | 57 | ||
58 | static inline unsigned int __xfrm4_addr_hash(xfrm_address_t *addr) | ||
59 | { | ||
60 | return ntohl(addr->a4); | ||
61 | } | ||
62 | |||
63 | static inline unsigned int __xfrm6_addr_hash(xfrm_address_t *addr) | ||
64 | { | ||
65 | return ntohl(addr->a6[2]^addr->a6[3]); | ||
66 | } | ||
67 | |||
68 | static inline unsigned int __xfrm4_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) | ||
69 | { | ||
70 | return ntohl(daddr->a4 ^ saddr->a4); | ||
71 | } | ||
72 | |||
73 | static inline unsigned int __xfrm6_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) | ||
74 | { | ||
75 | return ntohl(daddr->a6[2] ^ daddr->a6[3] ^ | ||
76 | saddr->a6[2] ^ saddr->a6[3]); | ||
77 | } | ||
78 | |||
79 | static inline unsigned int __xfrm_dst_hash(xfrm_address_t *daddr, | ||
80 | xfrm_address_t *saddr, | ||
81 | u32 reqid, unsigned short family, | ||
82 | unsigned int hmask) | ||
83 | { | ||
84 | unsigned int h = family ^ reqid; | ||
85 | switch (family) { | ||
86 | case AF_INET: | ||
87 | h ^= __xfrm4_daddr_saddr_hash(daddr, saddr); | ||
88 | break; | ||
89 | case AF_INET6: | ||
90 | h ^= __xfrm6_daddr_saddr_hash(daddr, saddr); | ||
91 | break; | ||
92 | }; | ||
93 | return (h ^ (h >> 16)) & hmask; | ||
94 | } | ||
95 | |||
96 | static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, | 58 | static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, |
97 | xfrm_address_t *saddr, | 59 | xfrm_address_t *saddr, |
98 | u32 reqid, | 60 | u32 reqid, |
@@ -101,76 +63,18 @@ static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, | |||
101 | return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask); | 63 | return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask); |
102 | } | 64 | } |
103 | 65 | ||
104 | static inline unsigned __xfrm_src_hash(xfrm_address_t *addr, unsigned short family, | 66 | static inline unsigned int xfrm_src_hash(xfrm_address_t *addr, |
105 | unsigned int hmask) | 67 | unsigned short family) |
106 | { | ||
107 | unsigned int h = family; | ||
108 | switch (family) { | ||
109 | case AF_INET: | ||
110 | h ^= __xfrm4_addr_hash(addr); | ||
111 | break; | ||
112 | case AF_INET6: | ||
113 | h ^= __xfrm6_addr_hash(addr); | ||
114 | break; | ||
115 | }; | ||
116 | return (h ^ (h >> 16)) & hmask; | ||
117 | } | ||
118 | |||
119 | static inline unsigned xfrm_src_hash(xfrm_address_t *addr, unsigned short family) | ||
120 | { | 68 | { |
121 | return __xfrm_src_hash(addr, family, xfrm_state_hmask); | 69 | return __xfrm_src_hash(addr, family, xfrm_state_hmask); |
122 | } | 70 | } |
123 | 71 | ||
124 | static inline unsigned int | 72 | static inline unsigned int |
125 | __xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, | ||
126 | unsigned short family, unsigned int hmask) | ||
127 | { | ||
128 | unsigned int h = spi ^ proto; | ||
129 | switch (family) { | ||
130 | case AF_INET: | ||
131 | h ^= __xfrm4_addr_hash(daddr); | ||
132 | break; | ||
133 | case AF_INET6: | ||
134 | h ^= __xfrm6_addr_hash(daddr); | ||
135 | break; | ||
136 | } | ||
137 | return (h ^ (h >> 10) ^ (h >> 20)) & hmask; | ||
138 | } | ||
139 | |||
140 | static inline unsigned int | ||
141 | xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family) | 73 | xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family) |
142 | { | 74 | { |
143 | return __xfrm_spi_hash(daddr, spi, proto, family, xfrm_state_hmask); | 75 | return __xfrm_spi_hash(daddr, spi, proto, family, xfrm_state_hmask); |
144 | } | 76 | } |
145 | 77 | ||
146 | static struct hlist_head *xfrm_state_hash_alloc(unsigned int sz) | ||
147 | { | ||
148 | struct hlist_head *n; | ||
149 | |||
150 | if (sz <= PAGE_SIZE) | ||
151 | n = kmalloc(sz, GFP_KERNEL); | ||
152 | else if (hashdist) | ||
153 | n = __vmalloc(sz, GFP_KERNEL, PAGE_KERNEL); | ||
154 | else | ||
155 | n = (struct hlist_head *) | ||
156 | __get_free_pages(GFP_KERNEL, get_order(sz)); | ||
157 | |||
158 | if (n) | ||
159 | memset(n, 0, sz); | ||
160 | |||
161 | return n; | ||
162 | } | ||
163 | |||
164 | static void xfrm_state_hash_free(struct hlist_head *n, unsigned int sz) | ||
165 | { | ||
166 | if (sz <= PAGE_SIZE) | ||
167 | kfree(n); | ||
168 | else if (hashdist) | ||
169 | vfree(n); | ||
170 | else | ||
171 | free_pages((unsigned long)n, get_order(sz)); | ||
172 | } | ||
173 | |||
174 | static void xfrm_hash_transfer(struct hlist_head *list, | 78 | static void xfrm_hash_transfer(struct hlist_head *list, |
175 | struct hlist_head *ndsttable, | 79 | struct hlist_head *ndsttable, |
176 | struct hlist_head *nsrctable, | 80 | struct hlist_head *nsrctable, |
@@ -216,18 +120,18 @@ static void xfrm_hash_resize(void *__unused) | |||
216 | mutex_lock(&hash_resize_mutex); | 120 | mutex_lock(&hash_resize_mutex); |
217 | 121 | ||
218 | nsize = xfrm_hash_new_size(); | 122 | nsize = xfrm_hash_new_size(); |
219 | ndst = xfrm_state_hash_alloc(nsize); | 123 | ndst = xfrm_hash_alloc(nsize); |
220 | if (!ndst) | 124 | if (!ndst) |
221 | goto out_unlock; | 125 | goto out_unlock; |
222 | nsrc = xfrm_state_hash_alloc(nsize); | 126 | nsrc = xfrm_hash_alloc(nsize); |
223 | if (!nsrc) { | 127 | if (!nsrc) { |
224 | xfrm_state_hash_free(ndst, nsize); | 128 | xfrm_hash_free(ndst, nsize); |
225 | goto out_unlock; | 129 | goto out_unlock; |
226 | } | 130 | } |
227 | nspi = xfrm_state_hash_alloc(nsize); | 131 | nspi = xfrm_hash_alloc(nsize); |
228 | if (!nspi) { | 132 | if (!nspi) { |
229 | xfrm_state_hash_free(ndst, nsize); | 133 | xfrm_hash_free(ndst, nsize); |
230 | xfrm_state_hash_free(nsrc, nsize); | 134 | xfrm_hash_free(nsrc, nsize); |
231 | goto out_unlock; | 135 | goto out_unlock; |
232 | } | 136 | } |
233 | 137 | ||
@@ -251,9 +155,9 @@ static void xfrm_hash_resize(void *__unused) | |||
251 | spin_unlock_bh(&xfrm_state_lock); | 155 | spin_unlock_bh(&xfrm_state_lock); |
252 | 156 | ||
253 | osize = (ohashmask + 1) * sizeof(struct hlist_head); | 157 | osize = (ohashmask + 1) * sizeof(struct hlist_head); |
254 | xfrm_state_hash_free(odst, osize); | 158 | xfrm_hash_free(odst, osize); |
255 | xfrm_state_hash_free(osrc, osize); | 159 | xfrm_hash_free(osrc, osize); |
256 | xfrm_state_hash_free(ospi, osize); | 160 | xfrm_hash_free(ospi, osize); |
257 | 161 | ||
258 | out_unlock: | 162 | out_unlock: |
259 | mutex_unlock(&hash_resize_mutex); | 163 | mutex_unlock(&hash_resize_mutex); |
@@ -1643,9 +1547,9 @@ void __init xfrm_state_init(void) | |||
1643 | 1547 | ||
1644 | sz = sizeof(struct hlist_head) * 8; | 1548 | sz = sizeof(struct hlist_head) * 8; |
1645 | 1549 | ||
1646 | xfrm_state_bydst = xfrm_state_hash_alloc(sz); | 1550 | xfrm_state_bydst = xfrm_hash_alloc(sz); |
1647 | xfrm_state_bysrc = xfrm_state_hash_alloc(sz); | 1551 | xfrm_state_bysrc = xfrm_hash_alloc(sz); |
1648 | xfrm_state_byspi = xfrm_state_hash_alloc(sz); | 1552 | xfrm_state_byspi = xfrm_hash_alloc(sz); |
1649 | if (!xfrm_state_bydst || !xfrm_state_bysrc || !xfrm_state_byspi) | 1553 | if (!xfrm_state_bydst || !xfrm_state_bysrc || !xfrm_state_byspi) |
1650 | panic("XFRM: Cannot allocate bydst/bysrc/byspi hashes."); | 1554 | panic("XFRM: Cannot allocate bydst/bysrc/byspi hashes."); |
1651 | xfrm_state_hmask = ((sz / sizeof(struct hlist_head)) - 1); | 1555 | xfrm_state_hmask = ((sz / sizeof(struct hlist_head)) - 1); |