aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_policy.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_policy.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_policy.c')
-rw-r--r--net/xfrm/xfrm_policy.c95
1 files changed, 8 insertions, 87 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 087a5443b051..b446ca31fecc 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -22,12 +22,12 @@
22#include <linux/netdevice.h> 22#include <linux/netdevice.h>
23#include <linux/netfilter.h> 23#include <linux/netfilter.h>
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/bootmem.h>
26#include <linux/vmalloc.h>
27#include <linux/cache.h> 25#include <linux/cache.h>
28#include <net/xfrm.h> 26#include <net/xfrm.h>
29#include <net/ip.h> 27#include <net/ip.h>
30 28
29#include "xfrm_hash.h"
30
31DEFINE_MUTEX(xfrm_cfg_mutex); 31DEFINE_MUTEX(xfrm_cfg_mutex);
32EXPORT_SYMBOL(xfrm_cfg_mutex); 32EXPORT_SYMBOL(xfrm_cfg_mutex);
33 33
@@ -409,62 +409,11 @@ static struct hlist_head *xfrm_policy_byidx __read_mostly;
409static unsigned int xfrm_idx_hmask __read_mostly; 409static unsigned int xfrm_idx_hmask __read_mostly;
410static unsigned int xfrm_policy_hashmax __read_mostly = 1 * 1024 * 1024; 410static unsigned int xfrm_policy_hashmax __read_mostly = 1 * 1024 * 1024;
411 411
412static inline unsigned int __idx_hash(u32 index, unsigned int hmask)
413{
414 return (index ^ (index >> 8)) & hmask;
415}
416
417static inline unsigned int idx_hash(u32 index) 412static inline unsigned int idx_hash(u32 index)
418{ 413{
419 return __idx_hash(index, xfrm_idx_hmask); 414 return __idx_hash(index, xfrm_idx_hmask);
420} 415}
421 416
422static inline unsigned int __sel_hash(struct xfrm_selector *sel, unsigned short family, unsigned int hmask)
423{
424 xfrm_address_t *daddr = &sel->daddr;
425 xfrm_address_t *saddr = &sel->saddr;
426 unsigned int h = 0;
427
428 switch (family) {
429 case AF_INET:
430 if (sel->prefixlen_d != 32 ||
431 sel->prefixlen_s != 32)
432 return hmask + 1;
433
434 h = ntohl(daddr->a4 ^ saddr->a4);
435 break;
436
437 case AF_INET6:
438 if (sel->prefixlen_d != 128 ||
439 sel->prefixlen_s != 128)
440 return hmask + 1;
441
442 h = ntohl(daddr->a6[2] ^ daddr->a6[3] ^
443 saddr->a6[2] ^ saddr->a6[3]);
444 break;
445 };
446 h ^= (h >> 16);
447 return h & hmask;
448}
449
450static inline unsigned int __addr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, unsigned int hmask)
451{
452 unsigned int h = 0;
453
454 switch (family) {
455 case AF_INET:
456 h = ntohl(daddr->a4 ^ saddr->a4);
457 break;
458
459 case AF_INET6:
460 h = ntohl(daddr->a6[2] ^ daddr->a6[3] ^
461 saddr->a6[2] ^ saddr->a6[3]);
462 break;
463 };
464 h ^= (h >> 16);
465 return h & hmask;
466}
467
468static struct hlist_head *policy_hash_bysel(struct xfrm_selector *sel, unsigned short family, int dir) 417static struct hlist_head *policy_hash_bysel(struct xfrm_selector *sel, unsigned short family, int dir)
469{ 418{
470 unsigned int hmask = xfrm_policy_bydst[dir].hmask; 419 unsigned int hmask = xfrm_policy_bydst[dir].hmask;
@@ -483,34 +432,6 @@ static struct hlist_head *policy_hash_direct(xfrm_address_t *daddr, xfrm_address
483 return xfrm_policy_bydst[dir].table + hash; 432 return xfrm_policy_bydst[dir].table + hash;
484} 433}
485 434
486static struct hlist_head *xfrm_policy_hash_alloc(unsigned int sz)
487{
488 struct hlist_head *n;
489
490 if (sz <= PAGE_SIZE)
491 n = kmalloc(sz, GFP_KERNEL);
492 else if (hashdist)
493 n = __vmalloc(sz, GFP_KERNEL, PAGE_KERNEL);
494 else
495 n = (struct hlist_head *)
496 __get_free_pages(GFP_KERNEL, get_order(sz));
497
498 if (n)
499 memset(n, 0, sz);
500
501 return n;
502}
503
504static void xfrm_policy_hash_free(struct hlist_head *n, unsigned int sz)
505{
506 if (sz <= PAGE_SIZE)
507 kfree(n);
508 else if (hashdist)
509 vfree(n);
510 else
511 free_pages((unsigned long)n, get_order(sz));
512}
513
514static void xfrm_dst_hash_transfer(struct hlist_head *list, 435static void xfrm_dst_hash_transfer(struct hlist_head *list,
515 struct hlist_head *ndsttable, 436 struct hlist_head *ndsttable,
516 unsigned int nhashmask) 437 unsigned int nhashmask)
@@ -553,7 +474,7 @@ static void xfrm_bydst_resize(int dir)
553 unsigned int nhashmask = xfrm_new_hash_mask(hmask); 474 unsigned int nhashmask = xfrm_new_hash_mask(hmask);
554 unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head); 475 unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head);
555 struct hlist_head *odst = xfrm_policy_bydst[dir].table; 476 struct hlist_head *odst = xfrm_policy_bydst[dir].table;
556 struct hlist_head *ndst = xfrm_policy_hash_alloc(nsize); 477 struct hlist_head *ndst = xfrm_hash_alloc(nsize);
557 int i; 478 int i;
558 479
559 if (!ndst) 480 if (!ndst)
@@ -569,7 +490,7 @@ static void xfrm_bydst_resize(int dir)
569 490
570 write_unlock_bh(&xfrm_policy_lock); 491 write_unlock_bh(&xfrm_policy_lock);
571 492
572 xfrm_policy_hash_free(odst, (hmask + 1) * sizeof(struct hlist_head)); 493 xfrm_hash_free(odst, (hmask + 1) * sizeof(struct hlist_head));
573} 494}
574 495
575static void xfrm_byidx_resize(int total) 496static void xfrm_byidx_resize(int total)
@@ -578,7 +499,7 @@ static void xfrm_byidx_resize(int total)
578 unsigned int nhashmask = xfrm_new_hash_mask(hmask); 499 unsigned int nhashmask = xfrm_new_hash_mask(hmask);
579 unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head); 500 unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head);
580 struct hlist_head *oidx = xfrm_policy_byidx; 501 struct hlist_head *oidx = xfrm_policy_byidx;
581 struct hlist_head *nidx = xfrm_policy_hash_alloc(nsize); 502 struct hlist_head *nidx = xfrm_hash_alloc(nsize);
582 int i; 503 int i;
583 504
584 if (!nidx) 505 if (!nidx)
@@ -594,7 +515,7 @@ static void xfrm_byidx_resize(int total)
594 515
595 write_unlock_bh(&xfrm_policy_lock); 516 write_unlock_bh(&xfrm_policy_lock);
596 517
597 xfrm_policy_hash_free(oidx, (hmask + 1) * sizeof(struct hlist_head)); 518 xfrm_hash_free(oidx, (hmask + 1) * sizeof(struct hlist_head));
598} 519}
599 520
600static inline int xfrm_bydst_should_resize(int dir, int *total) 521static inline int xfrm_bydst_should_resize(int dir, int *total)
@@ -2071,7 +1992,7 @@ static void __init xfrm_policy_init(void)
2071 hmask = 8 - 1; 1992 hmask = 8 - 1;
2072 sz = (hmask+1) * sizeof(struct hlist_head); 1993 sz = (hmask+1) * sizeof(struct hlist_head);
2073 1994
2074 xfrm_policy_byidx = xfrm_policy_hash_alloc(sz); 1995 xfrm_policy_byidx = xfrm_hash_alloc(sz);
2075 xfrm_idx_hmask = hmask; 1996 xfrm_idx_hmask = hmask;
2076 if (!xfrm_policy_byidx) 1997 if (!xfrm_policy_byidx)
2077 panic("XFRM: failed to allocate byidx hash\n"); 1998 panic("XFRM: failed to allocate byidx hash\n");
@@ -2082,7 +2003,7 @@ static void __init xfrm_policy_init(void)
2082 INIT_HLIST_HEAD(&xfrm_policy_inexact[dir]); 2003 INIT_HLIST_HEAD(&xfrm_policy_inexact[dir]);
2083 2004
2084 htab = &xfrm_policy_bydst[dir]; 2005 htab = &xfrm_policy_bydst[dir];
2085 htab->table = xfrm_policy_hash_alloc(sz); 2006 htab->table = xfrm_hash_alloc(sz);
2086 htab->hmask = hmask; 2007 htab->hmask = hmask;
2087 if (!htab->table) 2008 if (!htab->table)
2088 panic("XFRM: failed to allocate bydst hash\n"); 2009 panic("XFRM: failed to allocate bydst hash\n");