xfrm_state.c (c1969f294e624d5b642fc8e6ab9468b7c7791fa8) xfrm_state.c (44e36b42a8378be1dcf7e6f8a1cb2710a8903387)
1/*
2 * xfrm_state.c
3 *
4 * Changes:
5 * Mitsuru KANDA @USAGI
6 * Kazunori MIYAZAWA @USAGI
7 * Kunihiro Ishiguro <kunihiro@ipinfusion.com>
8 * IPv6 support

--- 4 unchanged lines hidden (view full) ---

13 *
14 */
15
16#include <linux/workqueue.h>
17#include <net/xfrm.h>
18#include <linux/pfkeyv2.h>
19#include <linux/ipsec.h>
20#include <linux/module.h>
1/*
2 * xfrm_state.c
3 *
4 * Changes:
5 * Mitsuru KANDA @USAGI
6 * Kazunori MIYAZAWA @USAGI
7 * Kunihiro Ishiguro <kunihiro@ipinfusion.com>
8 * IPv6 support

--- 4 unchanged lines hidden (view full) ---

13 *
14 */
15
16#include <linux/workqueue.h>
17#include <net/xfrm.h>
18#include <linux/pfkeyv2.h>
19#include <linux/ipsec.h>
20#include <linux/module.h>
21#include <linux/bootmem.h>
22#include <linux/vmalloc.h>
23#include <linux/cache.h>
24#include <asm/uaccess.h>
25
21#include <linux/cache.h>
22#include <asm/uaccess.h>
23
24#include "xfrm_hash.h"
25
26struct sock *xfrm_nl;
27EXPORT_SYMBOL(xfrm_nl);
28
29u32 sysctl_xfrm_aevent_etime = XFRM_AE_ETIME;
30EXPORT_SYMBOL(sysctl_xfrm_aevent_etime);
31
32u32 sysctl_xfrm_aevent_rseqth = XFRM_AE_SEQT_SIZE;
33EXPORT_SYMBOL(sysctl_xfrm_aevent_rseqth);

--- 16 unchanged lines hidden (view full) ---

50static struct hlist_head *xfrm_state_bydst __read_mostly;
51static struct hlist_head *xfrm_state_bysrc __read_mostly;
52static struct hlist_head *xfrm_state_byspi __read_mostly;
53static unsigned int xfrm_state_hmask __read_mostly;
54static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
55static unsigned int xfrm_state_num;
56static unsigned int xfrm_state_genid;
57
26struct sock *xfrm_nl;
27EXPORT_SYMBOL(xfrm_nl);
28
29u32 sysctl_xfrm_aevent_etime = XFRM_AE_ETIME;
30EXPORT_SYMBOL(sysctl_xfrm_aevent_etime);
31
32u32 sysctl_xfrm_aevent_rseqth = XFRM_AE_SEQT_SIZE;
33EXPORT_SYMBOL(sysctl_xfrm_aevent_rseqth);

--- 16 unchanged lines hidden (view full) ---

50static struct hlist_head *xfrm_state_bydst __read_mostly;
51static struct hlist_head *xfrm_state_bysrc __read_mostly;
52static struct hlist_head *xfrm_state_byspi __read_mostly;
53static unsigned int xfrm_state_hmask __read_mostly;
54static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
55static unsigned int xfrm_state_num;
56static unsigned int xfrm_state_genid;
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,
97 xfrm_address_t *saddr,
98 u32 reqid,
99 unsigned short family)
100{
101 return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask);
102}
103
58static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr,
59 xfrm_address_t *saddr,
60 u32 reqid,
61 unsigned short family)
62{
63 return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask);
64}
65
104static inline unsigned __xfrm_src_hash(xfrm_address_t *addr, unsigned short family,
105 unsigned int hmask)
66static inline unsigned int xfrm_src_hash(xfrm_address_t *addr,
67 unsigned short family)
106{
68{
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{
121 return __xfrm_src_hash(addr, family, xfrm_state_hmask);
122}
123
124static inline unsigned int
69 return __xfrm_src_hash(addr, family, xfrm_state_hmask);
70}
71
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)
142{
143 return __xfrm_spi_hash(daddr, spi, proto, family, xfrm_state_hmask);
144}
145
73xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family)
74{
75 return __xfrm_spi_hash(daddr, spi, proto, family, xfrm_state_hmask);
76}
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,
175 struct hlist_head *ndsttable,
176 struct hlist_head *nsrctable,
177 struct hlist_head *nspitable,
178 unsigned int nhashmask)
179{
180 struct hlist_node *entry, *tmp;
181 struct xfrm_state *x;

--- 29 unchanged lines hidden (view full) ---

211 struct hlist_head *ndst, *nsrc, *nspi, *odst, *osrc, *ospi;
212 unsigned long nsize, osize;
213 unsigned int nhashmask, ohashmask;
214 int i;
215
216 mutex_lock(&hash_resize_mutex);
217
218 nsize = xfrm_hash_new_size();
78static void xfrm_hash_transfer(struct hlist_head *list,
79 struct hlist_head *ndsttable,
80 struct hlist_head *nsrctable,
81 struct hlist_head *nspitable,
82 unsigned int nhashmask)
83{
84 struct hlist_node *entry, *tmp;
85 struct xfrm_state *x;

--- 29 unchanged lines hidden (view full) ---

115 struct hlist_head *ndst, *nsrc, *nspi, *odst, *osrc, *ospi;
116 unsigned long nsize, osize;
117 unsigned int nhashmask, ohashmask;
118 int i;
119
120 mutex_lock(&hash_resize_mutex);
121
122 nsize = xfrm_hash_new_size();
219 ndst = xfrm_state_hash_alloc(nsize);
123 ndst = xfrm_hash_alloc(nsize);
220 if (!ndst)
221 goto out_unlock;
124 if (!ndst)
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;
226 }
129 goto out_unlock;
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);
230 xfrm_state_hash_free(nsrc, nsize);
133 xfrm_hash_free(ndst, nsize);
134 xfrm_hash_free(nsrc, nsize);
231 goto out_unlock;
232 }
233
234 spin_lock_bh(&xfrm_state_lock);
235
236 nhashmask = (nsize / sizeof(struct hlist_head)) - 1U;
237 for (i = xfrm_state_hmask; i >= 0; i--)
238 xfrm_hash_transfer(xfrm_state_bydst+i, ndst, nsrc, nspi,

--- 7 unchanged lines hidden (view full) ---

246 xfrm_state_bydst = ndst;
247 xfrm_state_bysrc = nsrc;
248 xfrm_state_byspi = nspi;
249 xfrm_state_hmask = nhashmask;
250
251 spin_unlock_bh(&xfrm_state_lock);
252
253 osize = (ohashmask + 1) * sizeof(struct hlist_head);
135 goto out_unlock;
136 }
137
138 spin_lock_bh(&xfrm_state_lock);
139
140 nhashmask = (nsize / sizeof(struct hlist_head)) - 1U;
141 for (i = xfrm_state_hmask; i >= 0; i--)
142 xfrm_hash_transfer(xfrm_state_bydst+i, ndst, nsrc, nspi,

--- 7 unchanged lines hidden (view full) ---

150 xfrm_state_bydst = ndst;
151 xfrm_state_bysrc = nsrc;
152 xfrm_state_byspi = nspi;
153 xfrm_state_hmask = nhashmask;
154
155 spin_unlock_bh(&xfrm_state_lock);
156
157 osize = (ohashmask + 1) * sizeof(struct hlist_head);
254 xfrm_state_hash_free(odst, osize);
255 xfrm_state_hash_free(osrc, osize);
256 xfrm_state_hash_free(ospi, osize);
158 xfrm_hash_free(odst, osize);
159 xfrm_hash_free(osrc, osize);
160 xfrm_hash_free(ospi, osize);
257
258out_unlock:
259 mutex_unlock(&hash_resize_mutex);
260}
261
262static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize, NULL);
263
264DECLARE_WAIT_QUEUE_HEAD(km_waitq);

--- 1373 unchanged lines hidden (view full) ---

1638EXPORT_SYMBOL(xfrm_init_state);
1639
1640void __init xfrm_state_init(void)
1641{
1642 unsigned int sz;
1643
1644 sz = sizeof(struct hlist_head) * 8;
1645
161
162out_unlock:
163 mutex_unlock(&hash_resize_mutex);
164}
165
166static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize, NULL);
167
168DECLARE_WAIT_QUEUE_HEAD(km_waitq);

--- 1373 unchanged lines hidden (view full) ---

1542EXPORT_SYMBOL(xfrm_init_state);
1543
1544void __init xfrm_state_init(void)
1545{
1546 unsigned int sz;
1547
1548 sz = sizeof(struct hlist_head) * 8;
1549
1646 xfrm_state_bydst = xfrm_state_hash_alloc(sz);
1647 xfrm_state_bysrc = xfrm_state_hash_alloc(sz);
1648 xfrm_state_byspi = xfrm_state_hash_alloc(sz);
1550 xfrm_state_bydst = xfrm_hash_alloc(sz);
1551 xfrm_state_bysrc = xfrm_hash_alloc(sz);
1552 xfrm_state_byspi = xfrm_hash_alloc(sz);
1649 if (!xfrm_state_bydst || !xfrm_state_bysrc || !xfrm_state_byspi)
1650 panic("XFRM: Cannot allocate bydst/bysrc/byspi hashes.");
1651 xfrm_state_hmask = ((sz / sizeof(struct hlist_head)) - 1);
1652
1653 INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task, NULL);
1654}
1655
1553 if (!xfrm_state_bydst || !xfrm_state_bysrc || !xfrm_state_byspi)
1554 panic("XFRM: Cannot allocate bydst/bysrc/byspi hashes.");
1555 xfrm_state_hmask = ((sz / sizeof(struct hlist_head)) - 1);
1556
1557 INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task, NULL);
1558}
1559