Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 34613
b: refs/heads/master
c: 44e36b4
h: refs/heads/master
i:
  34611: ad2b6f5
v: v3
  • Loading branch information
David S. Miller committed Sep 22, 2006
1 parent 69450fd commit 925f53f
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 201 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2518c7c2b3d7f0a6b302b4efe17c911f8dd4049f
refs/heads/master: 44e36b42a8378be1dcf7e6f8a1cb2710a8903387
3 changes: 2 additions & 1 deletion trunk/net/xfrm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

41 changes: 41 additions & 0 deletions trunk/net/xfrm/xfrm_hash.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* 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));
}
128 changes: 128 additions & 0 deletions trunk/net/xfrm/xfrm_hash.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#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 */
95 changes: 8 additions & 87 deletions trunk/net/xfrm/xfrm_policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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");
Expand All @@ -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");
Expand Down
Loading

0 comments on commit 925f53f

Please sign in to comment.