summaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_hash.h
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-09-28 17:19:15 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-28 17:19:15 -0400
commitf5c7e1a47aeca2b31106aa94e7f4daa218e6c478 (patch)
treea5a0ed3429f83d7404dc4d8fe19ac060d6ddb307 /net/xfrm/xfrm_hash.h
parentfe2c5fb1ef24e97b7cf96e24200bbe503286cb95 (diff)
parent689f1c9de2abbd76fda224d12cea5f43568a4335 (diff)
downloadtalos-op-linux-f5c7e1a47aeca2b31106aa94e7f4daa218e6c478.tar.gz
talos-op-linux-f5c7e1a47aeca2b31106aa94e7f4daa218e6c478.zip
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next
Steffen Klassert says: ==================== pull request (net-next): ipsec-next 2014-09-25 1) Remove useless hash_resize_mutex in xfrm_hash_resize(). This mutex is used only there, but xfrm_hash_resize() can't be called concurrently at all. From Ying Xue. 2) Extend policy hashing to prefixed policies based on prefix lenght thresholds. From Christophe Gouault. 3) Make the policy hash table thresholds configurable via netlink. From Christophe Gouault. 4) Remove the maximum authentication length for AH. This was needed to limit stack usage. We switched already to allocate space, so no need to keep the limit. From Herbert Xu. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/xfrm/xfrm_hash.h')
-rw-r--r--net/xfrm/xfrm_hash.h76
1 files changed, 66 insertions, 10 deletions
diff --git a/net/xfrm/xfrm_hash.h b/net/xfrm/xfrm_hash.h
index 0622d319e1f2..666c5ffe929d 100644
--- a/net/xfrm/xfrm_hash.h
+++ b/net/xfrm/xfrm_hash.h
@@ -3,6 +3,7 @@
#include <linux/xfrm.h>
#include <linux/socket.h>
+#include <linux/jhash.h>
static inline unsigned int __xfrm4_addr_hash(const xfrm_address_t *addr)
{
@@ -28,6 +29,58 @@ static inline unsigned int __xfrm6_daddr_saddr_hash(const xfrm_address_t *daddr,
saddr->a6[2] ^ saddr->a6[3]);
}
+static inline u32 __bits2mask32(__u8 bits)
+{
+ u32 mask32 = 0xffffffff;
+
+ if (bits == 0)
+ mask32 = 0;
+ else if (bits < 32)
+ mask32 <<= (32 - bits);
+
+ return mask32;
+}
+
+static inline unsigned int __xfrm4_dpref_spref_hash(const xfrm_address_t *daddr,
+ const xfrm_address_t *saddr,
+ __u8 dbits,
+ __u8 sbits)
+{
+ return jhash_2words(ntohl(daddr->a4) & __bits2mask32(dbits),
+ ntohl(saddr->a4) & __bits2mask32(sbits),
+ 0);
+}
+
+static inline unsigned int __xfrm6_pref_hash(const xfrm_address_t *addr,
+ __u8 prefixlen)
+{
+ int pdw;
+ int pbi;
+ u32 initval = 0;
+
+ pdw = prefixlen >> 5; /* num of whole u32 in prefix */
+ pbi = prefixlen & 0x1f; /* num of bits in incomplete u32 in prefix */
+
+ if (pbi) {
+ __be32 mask;
+
+ mask = htonl((0xffffffff) << (32 - pbi));
+
+ initval = (__force u32)(addr->a6[pdw] & mask);
+ }
+
+ return jhash2((__force u32 *)addr->a6, pdw, initval);
+}
+
+static inline unsigned int __xfrm6_dpref_spref_hash(const xfrm_address_t *daddr,
+ const xfrm_address_t *saddr,
+ __u8 dbits,
+ __u8 sbits)
+{
+ return __xfrm6_pref_hash(daddr, dbits) ^
+ __xfrm6_pref_hash(saddr, sbits);
+}
+
static inline unsigned int __xfrm_dst_hash(const xfrm_address_t *daddr,
const xfrm_address_t *saddr,
u32 reqid, unsigned short family,
@@ -84,7 +137,8 @@ static inline unsigned int __idx_hash(u32 index, unsigned int hmask)
}
static inline unsigned int __sel_hash(const struct xfrm_selector *sel,
- unsigned short family, unsigned int hmask)
+ unsigned short family, unsigned int hmask,
+ u8 dbits, u8 sbits)
{
const xfrm_address_t *daddr = &sel->daddr;
const xfrm_address_t *saddr = &sel->saddr;
@@ -92,19 +146,19 @@ static inline unsigned int __sel_hash(const struct xfrm_selector *sel,
switch (family) {
case AF_INET:
- if (sel->prefixlen_d != 32 ||
- sel->prefixlen_s != 32)
+ if (sel->prefixlen_d < dbits ||
+ sel->prefixlen_s < sbits)
return hmask + 1;
- h = __xfrm4_daddr_saddr_hash(daddr, saddr);
+ h = __xfrm4_dpref_spref_hash(daddr, saddr, dbits, sbits);
break;
case AF_INET6:
- if (sel->prefixlen_d != 128 ||
- sel->prefixlen_s != 128)
+ if (sel->prefixlen_d < dbits ||
+ sel->prefixlen_s < sbits)
return hmask + 1;
- h = __xfrm6_daddr_saddr_hash(daddr, saddr);
+ h = __xfrm6_dpref_spref_hash(daddr, saddr, dbits, sbits);
break;
}
h ^= (h >> 16);
@@ -113,17 +167,19 @@ static inline unsigned int __sel_hash(const struct xfrm_selector *sel,
static inline unsigned int __addr_hash(const xfrm_address_t *daddr,
const xfrm_address_t *saddr,
- unsigned short family, unsigned int hmask)
+ unsigned short family,
+ unsigned int hmask,
+ u8 dbits, u8 sbits)
{
unsigned int h = 0;
switch (family) {
case AF_INET:
- h = __xfrm4_daddr_saddr_hash(daddr, saddr);
+ h = __xfrm4_dpref_spref_hash(daddr, saddr, dbits, sbits);
break;
case AF_INET6:
- h = __xfrm6_daddr_saddr_hash(daddr, saddr);
+ h = __xfrm6_dpref_spref_hash(daddr, saddr, dbits, sbits);
break;
}
h ^= (h >> 16);
OpenPOWER on IntegriCloud