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 |