aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_state.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-08-24 07:50:50 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 18:08:49 -0400
commit44e36b42a8378be1dcf7e6f8a1cb2710a8903387 (patch)
tree2c057957a4e4dc7f679ac671a9f091f3fe366b92 /net/xfrm/xfrm_state.c
parent2518c7c2b3d7f0a6b302b4efe17c911f8dd4049f (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.c128
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
26struct sock *xfrm_nl; 26struct sock *xfrm_nl;
27EXPORT_SYMBOL(xfrm_nl); 27EXPORT_SYMBOL(xfrm_nl);
28 28
@@ -55,44 +55,6 @@ static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
55static unsigned int xfrm_state_num; 55static unsigned int xfrm_state_num;
56static unsigned int xfrm_state_genid; 56static unsigned int xfrm_state_genid;
57 57
58static inline unsigned int __xfrm4_addr_hash(xfrm_address_t *addr)
59{
60 return ntohl(addr->a4);
61}
62
63static inline unsigned int __xfrm6_addr_hash(xfrm_address_t *addr)
64{
65 return ntohl(addr->a6[2]^addr->a6[3]);
66}
67
68static 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
73static 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
79static 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
96static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, 58static 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
104static inline unsigned __xfrm_src_hash(xfrm_address_t *addr, unsigned short family, 66static 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
119static 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
124static inline unsigned int 72static 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
140static inline unsigned int
141xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family) 73xfrm_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
146static 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
164static 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
174static void xfrm_hash_transfer(struct hlist_head *list, 78static 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
258out_unlock: 162out_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);