Loading net/xfrm/Makefile +2 −1 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ # Makefile for the XFRM subsystem. # obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_input.o xfrm_algo.o obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \ xfrm_input.o xfrm_algo.o obj-$(CONFIG_XFRM_USER) += xfrm_user.o net/xfrm/xfrm_hash.c 0 → 100644 +41 −0 Original line number Diff line number Diff line /* xfrm_hash.c: Common hash table code. * * Copyright (C) 2006 David S. Miller (davem@davemloft.net) */ #include <linux/kernel.h> #include <linux/mm.h> #include <linux/bootmem.h> #include <linux/vmalloc.h> #include <linux/slab.h> #include <linux/xfrm.h> #include "xfrm_hash.h" struct hlist_head *xfrm_hash_alloc(unsigned int sz) { struct hlist_head *n; if (sz <= PAGE_SIZE) n = kmalloc(sz, GFP_KERNEL); else if (hashdist) n = __vmalloc(sz, GFP_KERNEL, PAGE_KERNEL); else n = (struct hlist_head *) __get_free_pages(GFP_KERNEL, get_order(sz)); if (n) memset(n, 0, sz); return n; } void xfrm_hash_free(struct hlist_head *n, unsigned int sz) { if (sz <= PAGE_SIZE) kfree(n); else if (hashdist) vfree(n); else free_pages((unsigned long)n, get_order(sz)); } net/xfrm/xfrm_hash.h 0 → 100644 +128 −0 Original line number Diff line number Diff line #ifndef _XFRM_HASH_H #define _XFRM_HASH_H #include <linux/xfrm.h> #include <linux/socket.h> static inline unsigned int __xfrm4_addr_hash(xfrm_address_t *addr) { return ntohl(addr->a4); } static inline unsigned int __xfrm6_addr_hash(xfrm_address_t *addr) { return ntohl(addr->a6[2] ^ addr->a6[3]); } static inline unsigned int __xfrm4_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) { return ntohl(daddr->a4 ^ saddr->a4); } static inline unsigned int __xfrm6_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) { return ntohl(daddr->a6[2] ^ daddr->a6[3] ^ saddr->a6[2] ^ saddr->a6[3]); } static inline unsigned int __xfrm_dst_hash(xfrm_address_t *daddr, xfrm_address_t *saddr, u32 reqid, unsigned short family, unsigned int hmask) { unsigned int h = family ^ reqid; switch (family) { case AF_INET: h ^= __xfrm4_daddr_saddr_hash(daddr, saddr); break; case AF_INET6: h ^= __xfrm6_daddr_saddr_hash(daddr, saddr); break; } return (h ^ (h >> 16)) & hmask; } static inline unsigned __xfrm_src_hash(xfrm_address_t *saddr, unsigned short family, unsigned int hmask) { unsigned int h = family; switch (family) { case AF_INET: h ^= __xfrm4_addr_hash(saddr); break; case AF_INET6: h ^= __xfrm6_addr_hash(saddr); break; }; return (h ^ (h >> 16)) & hmask; } static inline unsigned int __xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family, unsigned int hmask) { unsigned int h = spi ^ proto; switch (family) { case AF_INET: h ^= __xfrm4_addr_hash(daddr); break; case AF_INET6: h ^= __xfrm6_addr_hash(daddr); break; } return (h ^ (h >> 10) ^ (h >> 20)) & hmask; } static inline unsigned int __idx_hash(u32 index, unsigned int hmask) { return (index ^ (index >> 8)) & hmask; } static inline unsigned int __sel_hash(struct xfrm_selector *sel, unsigned short family, unsigned int hmask) { xfrm_address_t *daddr = &sel->daddr; xfrm_address_t *saddr = &sel->saddr; unsigned int h = 0; switch (family) { case AF_INET: if (sel->prefixlen_d != 32 || sel->prefixlen_s != 32) return hmask + 1; h = __xfrm4_daddr_saddr_hash(daddr, saddr); break; case AF_INET6: if (sel->prefixlen_d != 128 || sel->prefixlen_s != 128) return hmask + 1; h = __xfrm6_daddr_saddr_hash(daddr, saddr); break; }; h ^= (h >> 16); return h & hmask; } static inline unsigned int __addr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, unsigned int hmask) { unsigned int h = 0; switch (family) { case AF_INET: h = __xfrm4_daddr_saddr_hash(daddr, saddr); break; case AF_INET6: h = __xfrm6_daddr_saddr_hash(daddr, saddr); break; }; h ^= (h >> 16); return h & hmask; } extern struct hlist_head *xfrm_hash_alloc(unsigned int sz); extern void xfrm_hash_free(struct hlist_head *n, unsigned int sz); #endif /* _XFRM_HASH_H */ net/xfrm/xfrm_policy.c +8 −87 Original line number Diff line number Diff line Loading @@ -22,12 +22,12 @@ #include <linux/netdevice.h> #include <linux/netfilter.h> #include <linux/module.h> #include <linux/bootmem.h> #include <linux/vmalloc.h> #include <linux/cache.h> #include <net/xfrm.h> #include <net/ip.h> #include "xfrm_hash.h" DEFINE_MUTEX(xfrm_cfg_mutex); EXPORT_SYMBOL(xfrm_cfg_mutex); Loading Loading @@ -409,62 +409,11 @@ static struct hlist_head *xfrm_policy_byidx __read_mostly; static unsigned int xfrm_idx_hmask __read_mostly; static unsigned int xfrm_policy_hashmax __read_mostly = 1 * 1024 * 1024; static inline unsigned int __idx_hash(u32 index, unsigned int hmask) { return (index ^ (index >> 8)) & hmask; } static inline unsigned int idx_hash(u32 index) { return __idx_hash(index, xfrm_idx_hmask); } static inline unsigned int __sel_hash(struct xfrm_selector *sel, unsigned short family, unsigned int hmask) { xfrm_address_t *daddr = &sel->daddr; xfrm_address_t *saddr = &sel->saddr; unsigned int h = 0; switch (family) { case AF_INET: if (sel->prefixlen_d != 32 || sel->prefixlen_s != 32) return hmask + 1; h = ntohl(daddr->a4 ^ saddr->a4); break; case AF_INET6: if (sel->prefixlen_d != 128 || sel->prefixlen_s != 128) return hmask + 1; h = ntohl(daddr->a6[2] ^ daddr->a6[3] ^ saddr->a6[2] ^ saddr->a6[3]); break; }; h ^= (h >> 16); return h & hmask; } static inline unsigned int __addr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, unsigned int hmask) { unsigned int h = 0; switch (family) { case AF_INET: h = ntohl(daddr->a4 ^ saddr->a4); break; case AF_INET6: h = ntohl(daddr->a6[2] ^ daddr->a6[3] ^ saddr->a6[2] ^ saddr->a6[3]); break; }; h ^= (h >> 16); return h & hmask; } static struct hlist_head *policy_hash_bysel(struct xfrm_selector *sel, unsigned short family, int dir) { unsigned int hmask = xfrm_policy_bydst[dir].hmask; Loading @@ -483,34 +432,6 @@ static struct hlist_head *policy_hash_direct(xfrm_address_t *daddr, xfrm_address return xfrm_policy_bydst[dir].table + hash; } static struct hlist_head *xfrm_policy_hash_alloc(unsigned int sz) { struct hlist_head *n; if (sz <= PAGE_SIZE) n = kmalloc(sz, GFP_KERNEL); else if (hashdist) n = __vmalloc(sz, GFP_KERNEL, PAGE_KERNEL); else n = (struct hlist_head *) __get_free_pages(GFP_KERNEL, get_order(sz)); if (n) memset(n, 0, sz); return n; } static void xfrm_policy_hash_free(struct hlist_head *n, unsigned int sz) { if (sz <= PAGE_SIZE) kfree(n); else if (hashdist) vfree(n); else free_pages((unsigned long)n, get_order(sz)); } static void xfrm_dst_hash_transfer(struct hlist_head *list, struct hlist_head *ndsttable, unsigned int nhashmask) Loading Loading @@ -553,7 +474,7 @@ static void xfrm_bydst_resize(int dir) unsigned int nhashmask = xfrm_new_hash_mask(hmask); unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head); struct hlist_head *odst = xfrm_policy_bydst[dir].table; struct hlist_head *ndst = xfrm_policy_hash_alloc(nsize); struct hlist_head *ndst = xfrm_hash_alloc(nsize); int i; if (!ndst) Loading @@ -569,7 +490,7 @@ static void xfrm_bydst_resize(int dir) write_unlock_bh(&xfrm_policy_lock); xfrm_policy_hash_free(odst, (hmask + 1) * sizeof(struct hlist_head)); xfrm_hash_free(odst, (hmask + 1) * sizeof(struct hlist_head)); } static void xfrm_byidx_resize(int total) Loading @@ -578,7 +499,7 @@ static void xfrm_byidx_resize(int total) unsigned int nhashmask = xfrm_new_hash_mask(hmask); unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head); struct hlist_head *oidx = xfrm_policy_byidx; struct hlist_head *nidx = xfrm_policy_hash_alloc(nsize); struct hlist_head *nidx = xfrm_hash_alloc(nsize); int i; if (!nidx) Loading @@ -594,7 +515,7 @@ static void xfrm_byidx_resize(int total) write_unlock_bh(&xfrm_policy_lock); xfrm_policy_hash_free(oidx, (hmask + 1) * sizeof(struct hlist_head)); xfrm_hash_free(oidx, (hmask + 1) * sizeof(struct hlist_head)); } static inline int xfrm_bydst_should_resize(int dir, int *total) Loading Loading @@ -2071,7 +1992,7 @@ static void __init xfrm_policy_init(void) hmask = 8 - 1; sz = (hmask+1) * sizeof(struct hlist_head); xfrm_policy_byidx = xfrm_policy_hash_alloc(sz); xfrm_policy_byidx = xfrm_hash_alloc(sz); xfrm_idx_hmask = hmask; if (!xfrm_policy_byidx) panic("XFRM: failed to allocate byidx hash\n"); Loading @@ -2082,7 +2003,7 @@ static void __init xfrm_policy_init(void) INIT_HLIST_HEAD(&xfrm_policy_inexact[dir]); htab = &xfrm_policy_bydst[dir]; htab->table = xfrm_policy_hash_alloc(sz); htab->table = xfrm_hash_alloc(sz); htab->hmask = hmask; if (!htab->table) panic("XFRM: failed to allocate bydst hash\n"); Loading net/xfrm/xfrm_state.c +16 −112 Original line number Diff line number Diff line Loading @@ -18,11 +18,11 @@ #include <linux/pfkeyv2.h> #include <linux/ipsec.h> #include <linux/module.h> #include <linux/bootmem.h> #include <linux/vmalloc.h> #include <linux/cache.h> #include <asm/uaccess.h> #include "xfrm_hash.h" struct sock *xfrm_nl; EXPORT_SYMBOL(xfrm_nl); Loading Loading @@ -55,44 +55,6 @@ static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024; static unsigned int xfrm_state_num; static unsigned int xfrm_state_genid; static inline unsigned int __xfrm4_addr_hash(xfrm_address_t *addr) { return ntohl(addr->a4); } static inline unsigned int __xfrm6_addr_hash(xfrm_address_t *addr) { return ntohl(addr->a6[2]^addr->a6[3]); } static inline unsigned int __xfrm4_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) { return ntohl(daddr->a4 ^ saddr->a4); } static inline unsigned int __xfrm6_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) { return ntohl(daddr->a6[2] ^ daddr->a6[3] ^ saddr->a6[2] ^ saddr->a6[3]); } static inline unsigned int __xfrm_dst_hash(xfrm_address_t *daddr, xfrm_address_t *saddr, u32 reqid, unsigned short family, unsigned int hmask) { unsigned int h = family ^ reqid; switch (family) { case AF_INET: h ^= __xfrm4_daddr_saddr_hash(daddr, saddr); break; case AF_INET6: h ^= __xfrm6_daddr_saddr_hash(daddr, saddr); break; }; return (h ^ (h >> 16)) & hmask; } static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, xfrm_address_t *saddr, u32 reqid, Loading @@ -101,76 +63,18 @@ static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask); } static inline unsigned __xfrm_src_hash(xfrm_address_t *addr, unsigned short family, unsigned int hmask) { unsigned int h = family; switch (family) { case AF_INET: h ^= __xfrm4_addr_hash(addr); break; case AF_INET6: h ^= __xfrm6_addr_hash(addr); break; }; return (h ^ (h >> 16)) & hmask; } static inline unsigned xfrm_src_hash(xfrm_address_t *addr, unsigned short family) static inline unsigned int xfrm_src_hash(xfrm_address_t *addr, unsigned short family) { return __xfrm_src_hash(addr, family, xfrm_state_hmask); } static inline unsigned int __xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family, unsigned int hmask) { unsigned int h = spi ^ proto; switch (family) { case AF_INET: h ^= __xfrm4_addr_hash(daddr); break; case AF_INET6: h ^= __xfrm6_addr_hash(daddr); break; } return (h ^ (h >> 10) ^ (h >> 20)) & hmask; } static inline unsigned int xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family) { return __xfrm_spi_hash(daddr, spi, proto, family, xfrm_state_hmask); } static struct hlist_head *xfrm_state_hash_alloc(unsigned int sz) { struct hlist_head *n; if (sz <= PAGE_SIZE) n = kmalloc(sz, GFP_KERNEL); else if (hashdist) n = __vmalloc(sz, GFP_KERNEL, PAGE_KERNEL); else n = (struct hlist_head *) __get_free_pages(GFP_KERNEL, get_order(sz)); if (n) memset(n, 0, sz); return n; } static void xfrm_state_hash_free(struct hlist_head *n, unsigned int sz) { if (sz <= PAGE_SIZE) kfree(n); else if (hashdist) vfree(n); else free_pages((unsigned long)n, get_order(sz)); } static void xfrm_hash_transfer(struct hlist_head *list, struct hlist_head *ndsttable, struct hlist_head *nsrctable, Loading Loading @@ -216,18 +120,18 @@ static void xfrm_hash_resize(void *__unused) mutex_lock(&hash_resize_mutex); nsize = xfrm_hash_new_size(); ndst = xfrm_state_hash_alloc(nsize); ndst = xfrm_hash_alloc(nsize); if (!ndst) goto out_unlock; nsrc = xfrm_state_hash_alloc(nsize); nsrc = xfrm_hash_alloc(nsize); if (!nsrc) { xfrm_state_hash_free(ndst, nsize); xfrm_hash_free(ndst, nsize); goto out_unlock; } nspi = xfrm_state_hash_alloc(nsize); nspi = xfrm_hash_alloc(nsize); if (!nspi) { xfrm_state_hash_free(ndst, nsize); xfrm_state_hash_free(nsrc, nsize); xfrm_hash_free(ndst, nsize); xfrm_hash_free(nsrc, nsize); goto out_unlock; } Loading @@ -251,9 +155,9 @@ static void xfrm_hash_resize(void *__unused) spin_unlock_bh(&xfrm_state_lock); osize = (ohashmask + 1) * sizeof(struct hlist_head); xfrm_state_hash_free(odst, osize); xfrm_state_hash_free(osrc, osize); xfrm_state_hash_free(ospi, osize); xfrm_hash_free(odst, osize); xfrm_hash_free(osrc, osize); xfrm_hash_free(ospi, osize); out_unlock: mutex_unlock(&hash_resize_mutex); Loading Loading @@ -1643,9 +1547,9 @@ void __init xfrm_state_init(void) sz = sizeof(struct hlist_head) * 8; xfrm_state_bydst = xfrm_state_hash_alloc(sz); xfrm_state_bysrc = xfrm_state_hash_alloc(sz); xfrm_state_byspi = xfrm_state_hash_alloc(sz); xfrm_state_bydst = xfrm_hash_alloc(sz); xfrm_state_bysrc = xfrm_hash_alloc(sz); xfrm_state_byspi = xfrm_hash_alloc(sz); if (!xfrm_state_bydst || !xfrm_state_bysrc || !xfrm_state_byspi) panic("XFRM: Cannot allocate bydst/bysrc/byspi hashes."); xfrm_state_hmask = ((sz / sizeof(struct hlist_head)) - 1); Loading Loading
net/xfrm/Makefile +2 −1 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ # Makefile for the XFRM subsystem. # obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_input.o xfrm_algo.o obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \ xfrm_input.o xfrm_algo.o obj-$(CONFIG_XFRM_USER) += xfrm_user.o
net/xfrm/xfrm_hash.c 0 → 100644 +41 −0 Original line number Diff line number Diff line /* xfrm_hash.c: Common hash table code. * * Copyright (C) 2006 David S. Miller (davem@davemloft.net) */ #include <linux/kernel.h> #include <linux/mm.h> #include <linux/bootmem.h> #include <linux/vmalloc.h> #include <linux/slab.h> #include <linux/xfrm.h> #include "xfrm_hash.h" struct hlist_head *xfrm_hash_alloc(unsigned int sz) { struct hlist_head *n; if (sz <= PAGE_SIZE) n = kmalloc(sz, GFP_KERNEL); else if (hashdist) n = __vmalloc(sz, GFP_KERNEL, PAGE_KERNEL); else n = (struct hlist_head *) __get_free_pages(GFP_KERNEL, get_order(sz)); if (n) memset(n, 0, sz); return n; } void xfrm_hash_free(struct hlist_head *n, unsigned int sz) { if (sz <= PAGE_SIZE) kfree(n); else if (hashdist) vfree(n); else free_pages((unsigned long)n, get_order(sz)); }
net/xfrm/xfrm_hash.h 0 → 100644 +128 −0 Original line number Diff line number Diff line #ifndef _XFRM_HASH_H #define _XFRM_HASH_H #include <linux/xfrm.h> #include <linux/socket.h> static inline unsigned int __xfrm4_addr_hash(xfrm_address_t *addr) { return ntohl(addr->a4); } static inline unsigned int __xfrm6_addr_hash(xfrm_address_t *addr) { return ntohl(addr->a6[2] ^ addr->a6[3]); } static inline unsigned int __xfrm4_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) { return ntohl(daddr->a4 ^ saddr->a4); } static inline unsigned int __xfrm6_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) { return ntohl(daddr->a6[2] ^ daddr->a6[3] ^ saddr->a6[2] ^ saddr->a6[3]); } static inline unsigned int __xfrm_dst_hash(xfrm_address_t *daddr, xfrm_address_t *saddr, u32 reqid, unsigned short family, unsigned int hmask) { unsigned int h = family ^ reqid; switch (family) { case AF_INET: h ^= __xfrm4_daddr_saddr_hash(daddr, saddr); break; case AF_INET6: h ^= __xfrm6_daddr_saddr_hash(daddr, saddr); break; } return (h ^ (h >> 16)) & hmask; } static inline unsigned __xfrm_src_hash(xfrm_address_t *saddr, unsigned short family, unsigned int hmask) { unsigned int h = family; switch (family) { case AF_INET: h ^= __xfrm4_addr_hash(saddr); break; case AF_INET6: h ^= __xfrm6_addr_hash(saddr); break; }; return (h ^ (h >> 16)) & hmask; } static inline unsigned int __xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family, unsigned int hmask) { unsigned int h = spi ^ proto; switch (family) { case AF_INET: h ^= __xfrm4_addr_hash(daddr); break; case AF_INET6: h ^= __xfrm6_addr_hash(daddr); break; } return (h ^ (h >> 10) ^ (h >> 20)) & hmask; } static inline unsigned int __idx_hash(u32 index, unsigned int hmask) { return (index ^ (index >> 8)) & hmask; } static inline unsigned int __sel_hash(struct xfrm_selector *sel, unsigned short family, unsigned int hmask) { xfrm_address_t *daddr = &sel->daddr; xfrm_address_t *saddr = &sel->saddr; unsigned int h = 0; switch (family) { case AF_INET: if (sel->prefixlen_d != 32 || sel->prefixlen_s != 32) return hmask + 1; h = __xfrm4_daddr_saddr_hash(daddr, saddr); break; case AF_INET6: if (sel->prefixlen_d != 128 || sel->prefixlen_s != 128) return hmask + 1; h = __xfrm6_daddr_saddr_hash(daddr, saddr); break; }; h ^= (h >> 16); return h & hmask; } static inline unsigned int __addr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, unsigned int hmask) { unsigned int h = 0; switch (family) { case AF_INET: h = __xfrm4_daddr_saddr_hash(daddr, saddr); break; case AF_INET6: h = __xfrm6_daddr_saddr_hash(daddr, saddr); break; }; h ^= (h >> 16); return h & hmask; } extern struct hlist_head *xfrm_hash_alloc(unsigned int sz); extern void xfrm_hash_free(struct hlist_head *n, unsigned int sz); #endif /* _XFRM_HASH_H */
net/xfrm/xfrm_policy.c +8 −87 Original line number Diff line number Diff line Loading @@ -22,12 +22,12 @@ #include <linux/netdevice.h> #include <linux/netfilter.h> #include <linux/module.h> #include <linux/bootmem.h> #include <linux/vmalloc.h> #include <linux/cache.h> #include <net/xfrm.h> #include <net/ip.h> #include "xfrm_hash.h" DEFINE_MUTEX(xfrm_cfg_mutex); EXPORT_SYMBOL(xfrm_cfg_mutex); Loading Loading @@ -409,62 +409,11 @@ static struct hlist_head *xfrm_policy_byidx __read_mostly; static unsigned int xfrm_idx_hmask __read_mostly; static unsigned int xfrm_policy_hashmax __read_mostly = 1 * 1024 * 1024; static inline unsigned int __idx_hash(u32 index, unsigned int hmask) { return (index ^ (index >> 8)) & hmask; } static inline unsigned int idx_hash(u32 index) { return __idx_hash(index, xfrm_idx_hmask); } static inline unsigned int __sel_hash(struct xfrm_selector *sel, unsigned short family, unsigned int hmask) { xfrm_address_t *daddr = &sel->daddr; xfrm_address_t *saddr = &sel->saddr; unsigned int h = 0; switch (family) { case AF_INET: if (sel->prefixlen_d != 32 || sel->prefixlen_s != 32) return hmask + 1; h = ntohl(daddr->a4 ^ saddr->a4); break; case AF_INET6: if (sel->prefixlen_d != 128 || sel->prefixlen_s != 128) return hmask + 1; h = ntohl(daddr->a6[2] ^ daddr->a6[3] ^ saddr->a6[2] ^ saddr->a6[3]); break; }; h ^= (h >> 16); return h & hmask; } static inline unsigned int __addr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, unsigned int hmask) { unsigned int h = 0; switch (family) { case AF_INET: h = ntohl(daddr->a4 ^ saddr->a4); break; case AF_INET6: h = ntohl(daddr->a6[2] ^ daddr->a6[3] ^ saddr->a6[2] ^ saddr->a6[3]); break; }; h ^= (h >> 16); return h & hmask; } static struct hlist_head *policy_hash_bysel(struct xfrm_selector *sel, unsigned short family, int dir) { unsigned int hmask = xfrm_policy_bydst[dir].hmask; Loading @@ -483,34 +432,6 @@ static struct hlist_head *policy_hash_direct(xfrm_address_t *daddr, xfrm_address return xfrm_policy_bydst[dir].table + hash; } static struct hlist_head *xfrm_policy_hash_alloc(unsigned int sz) { struct hlist_head *n; if (sz <= PAGE_SIZE) n = kmalloc(sz, GFP_KERNEL); else if (hashdist) n = __vmalloc(sz, GFP_KERNEL, PAGE_KERNEL); else n = (struct hlist_head *) __get_free_pages(GFP_KERNEL, get_order(sz)); if (n) memset(n, 0, sz); return n; } static void xfrm_policy_hash_free(struct hlist_head *n, unsigned int sz) { if (sz <= PAGE_SIZE) kfree(n); else if (hashdist) vfree(n); else free_pages((unsigned long)n, get_order(sz)); } static void xfrm_dst_hash_transfer(struct hlist_head *list, struct hlist_head *ndsttable, unsigned int nhashmask) Loading Loading @@ -553,7 +474,7 @@ static void xfrm_bydst_resize(int dir) unsigned int nhashmask = xfrm_new_hash_mask(hmask); unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head); struct hlist_head *odst = xfrm_policy_bydst[dir].table; struct hlist_head *ndst = xfrm_policy_hash_alloc(nsize); struct hlist_head *ndst = xfrm_hash_alloc(nsize); int i; if (!ndst) Loading @@ -569,7 +490,7 @@ static void xfrm_bydst_resize(int dir) write_unlock_bh(&xfrm_policy_lock); xfrm_policy_hash_free(odst, (hmask + 1) * sizeof(struct hlist_head)); xfrm_hash_free(odst, (hmask + 1) * sizeof(struct hlist_head)); } static void xfrm_byidx_resize(int total) Loading @@ -578,7 +499,7 @@ static void xfrm_byidx_resize(int total) unsigned int nhashmask = xfrm_new_hash_mask(hmask); unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head); struct hlist_head *oidx = xfrm_policy_byidx; struct hlist_head *nidx = xfrm_policy_hash_alloc(nsize); struct hlist_head *nidx = xfrm_hash_alloc(nsize); int i; if (!nidx) Loading @@ -594,7 +515,7 @@ static void xfrm_byidx_resize(int total) write_unlock_bh(&xfrm_policy_lock); xfrm_policy_hash_free(oidx, (hmask + 1) * sizeof(struct hlist_head)); xfrm_hash_free(oidx, (hmask + 1) * sizeof(struct hlist_head)); } static inline int xfrm_bydst_should_resize(int dir, int *total) Loading Loading @@ -2071,7 +1992,7 @@ static void __init xfrm_policy_init(void) hmask = 8 - 1; sz = (hmask+1) * sizeof(struct hlist_head); xfrm_policy_byidx = xfrm_policy_hash_alloc(sz); xfrm_policy_byidx = xfrm_hash_alloc(sz); xfrm_idx_hmask = hmask; if (!xfrm_policy_byidx) panic("XFRM: failed to allocate byidx hash\n"); Loading @@ -2082,7 +2003,7 @@ static void __init xfrm_policy_init(void) INIT_HLIST_HEAD(&xfrm_policy_inexact[dir]); htab = &xfrm_policy_bydst[dir]; htab->table = xfrm_policy_hash_alloc(sz); htab->table = xfrm_hash_alloc(sz); htab->hmask = hmask; if (!htab->table) panic("XFRM: failed to allocate bydst hash\n"); Loading
net/xfrm/xfrm_state.c +16 −112 Original line number Diff line number Diff line Loading @@ -18,11 +18,11 @@ #include <linux/pfkeyv2.h> #include <linux/ipsec.h> #include <linux/module.h> #include <linux/bootmem.h> #include <linux/vmalloc.h> #include <linux/cache.h> #include <asm/uaccess.h> #include "xfrm_hash.h" struct sock *xfrm_nl; EXPORT_SYMBOL(xfrm_nl); Loading Loading @@ -55,44 +55,6 @@ static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024; static unsigned int xfrm_state_num; static unsigned int xfrm_state_genid; static inline unsigned int __xfrm4_addr_hash(xfrm_address_t *addr) { return ntohl(addr->a4); } static inline unsigned int __xfrm6_addr_hash(xfrm_address_t *addr) { return ntohl(addr->a6[2]^addr->a6[3]); } static inline unsigned int __xfrm4_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) { return ntohl(daddr->a4 ^ saddr->a4); } static inline unsigned int __xfrm6_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) { return ntohl(daddr->a6[2] ^ daddr->a6[3] ^ saddr->a6[2] ^ saddr->a6[3]); } static inline unsigned int __xfrm_dst_hash(xfrm_address_t *daddr, xfrm_address_t *saddr, u32 reqid, unsigned short family, unsigned int hmask) { unsigned int h = family ^ reqid; switch (family) { case AF_INET: h ^= __xfrm4_daddr_saddr_hash(daddr, saddr); break; case AF_INET6: h ^= __xfrm6_daddr_saddr_hash(daddr, saddr); break; }; return (h ^ (h >> 16)) & hmask; } static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, xfrm_address_t *saddr, u32 reqid, Loading @@ -101,76 +63,18 @@ static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask); } static inline unsigned __xfrm_src_hash(xfrm_address_t *addr, unsigned short family, unsigned int hmask) { unsigned int h = family; switch (family) { case AF_INET: h ^= __xfrm4_addr_hash(addr); break; case AF_INET6: h ^= __xfrm6_addr_hash(addr); break; }; return (h ^ (h >> 16)) & hmask; } static inline unsigned xfrm_src_hash(xfrm_address_t *addr, unsigned short family) static inline unsigned int xfrm_src_hash(xfrm_address_t *addr, unsigned short family) { return __xfrm_src_hash(addr, family, xfrm_state_hmask); } static inline unsigned int __xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family, unsigned int hmask) { unsigned int h = spi ^ proto; switch (family) { case AF_INET: h ^= __xfrm4_addr_hash(daddr); break; case AF_INET6: h ^= __xfrm6_addr_hash(daddr); break; } return (h ^ (h >> 10) ^ (h >> 20)) & hmask; } static inline unsigned int xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family) { return __xfrm_spi_hash(daddr, spi, proto, family, xfrm_state_hmask); } static struct hlist_head *xfrm_state_hash_alloc(unsigned int sz) { struct hlist_head *n; if (sz <= PAGE_SIZE) n = kmalloc(sz, GFP_KERNEL); else if (hashdist) n = __vmalloc(sz, GFP_KERNEL, PAGE_KERNEL); else n = (struct hlist_head *) __get_free_pages(GFP_KERNEL, get_order(sz)); if (n) memset(n, 0, sz); return n; } static void xfrm_state_hash_free(struct hlist_head *n, unsigned int sz) { if (sz <= PAGE_SIZE) kfree(n); else if (hashdist) vfree(n); else free_pages((unsigned long)n, get_order(sz)); } static void xfrm_hash_transfer(struct hlist_head *list, struct hlist_head *ndsttable, struct hlist_head *nsrctable, Loading Loading @@ -216,18 +120,18 @@ static void xfrm_hash_resize(void *__unused) mutex_lock(&hash_resize_mutex); nsize = xfrm_hash_new_size(); ndst = xfrm_state_hash_alloc(nsize); ndst = xfrm_hash_alloc(nsize); if (!ndst) goto out_unlock; nsrc = xfrm_state_hash_alloc(nsize); nsrc = xfrm_hash_alloc(nsize); if (!nsrc) { xfrm_state_hash_free(ndst, nsize); xfrm_hash_free(ndst, nsize); goto out_unlock; } nspi = xfrm_state_hash_alloc(nsize); nspi = xfrm_hash_alloc(nsize); if (!nspi) { xfrm_state_hash_free(ndst, nsize); xfrm_state_hash_free(nsrc, nsize); xfrm_hash_free(ndst, nsize); xfrm_hash_free(nsrc, nsize); goto out_unlock; } Loading @@ -251,9 +155,9 @@ static void xfrm_hash_resize(void *__unused) spin_unlock_bh(&xfrm_state_lock); osize = (ohashmask + 1) * sizeof(struct hlist_head); xfrm_state_hash_free(odst, osize); xfrm_state_hash_free(osrc, osize); xfrm_state_hash_free(ospi, osize); xfrm_hash_free(odst, osize); xfrm_hash_free(osrc, osize); xfrm_hash_free(ospi, osize); out_unlock: mutex_unlock(&hash_resize_mutex); Loading Loading @@ -1643,9 +1547,9 @@ void __init xfrm_state_init(void) sz = sizeof(struct hlist_head) * 8; xfrm_state_bydst = xfrm_state_hash_alloc(sz); xfrm_state_bysrc = xfrm_state_hash_alloc(sz); xfrm_state_byspi = xfrm_state_hash_alloc(sz); xfrm_state_bydst = xfrm_hash_alloc(sz); xfrm_state_bysrc = xfrm_hash_alloc(sz); xfrm_state_byspi = xfrm_hash_alloc(sz); if (!xfrm_state_bydst || !xfrm_state_bysrc || !xfrm_state_byspi) panic("XFRM: Cannot allocate bydst/bysrc/byspi hashes."); xfrm_state_hmask = ((sz / sizeof(struct hlist_head)) - 1); Loading