diff options
Diffstat (limited to 'net/xfrm/xfrm_hash.h')
-rw-r--r-- | net/xfrm/xfrm_hash.h | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/net/xfrm/xfrm_hash.h b/net/xfrm/xfrm_hash.h new file mode 100644 index 000000000000..d3abb0b7dc62 --- /dev/null +++ b/net/xfrm/xfrm_hash.h | |||
@@ -0,0 +1,128 @@ | |||
1 | #ifndef _XFRM_HASH_H | ||
2 | #define _XFRM_HASH_H | ||
3 | |||
4 | #include <linux/xfrm.h> | ||
5 | #include <linux/socket.h> | ||
6 | |||
7 | static inline unsigned int __xfrm4_addr_hash(xfrm_address_t *addr) | ||
8 | { | ||
9 | return ntohl(addr->a4); | ||
10 | } | ||
11 | |||
12 | static inline unsigned int __xfrm6_addr_hash(xfrm_address_t *addr) | ||
13 | { | ||
14 | return ntohl(addr->a6[2] ^ addr->a6[3]); | ||
15 | } | ||
16 | |||
17 | static inline unsigned int __xfrm4_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) | ||
18 | { | ||
19 | return ntohl(daddr->a4 ^ saddr->a4); | ||
20 | } | ||
21 | |||
22 | static inline unsigned int __xfrm6_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) | ||
23 | { | ||
24 | return ntohl(daddr->a6[2] ^ daddr->a6[3] ^ | ||
25 | saddr->a6[2] ^ saddr->a6[3]); | ||
26 | } | ||
27 | |||
28 | static inline unsigned int __xfrm_dst_hash(xfrm_address_t *daddr, xfrm_address_t *saddr, | ||
29 | u32 reqid, unsigned short family, | ||
30 | unsigned int hmask) | ||
31 | { | ||
32 | unsigned int h = family ^ reqid; | ||
33 | switch (family) { | ||
34 | case AF_INET: | ||
35 | h ^= __xfrm4_daddr_saddr_hash(daddr, saddr); | ||
36 | break; | ||
37 | case AF_INET6: | ||
38 | h ^= __xfrm6_daddr_saddr_hash(daddr, saddr); | ||
39 | break; | ||
40 | } | ||
41 | return (h ^ (h >> 16)) & hmask; | ||
42 | } | ||
43 | |||
44 | static inline unsigned __xfrm_src_hash(xfrm_address_t *saddr, | ||
45 | unsigned short family, | ||
46 | unsigned int hmask) | ||
47 | { | ||
48 | unsigned int h = family; | ||
49 | switch (family) { | ||
50 | case AF_INET: | ||
51 | h ^= __xfrm4_addr_hash(saddr); | ||
52 | break; | ||
53 | case AF_INET6: | ||
54 | h ^= __xfrm6_addr_hash(saddr); | ||
55 | break; | ||
56 | }; | ||
57 | return (h ^ (h >> 16)) & hmask; | ||
58 | } | ||
59 | |||
60 | static inline unsigned int | ||
61 | __xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family, | ||
62 | unsigned int hmask) | ||
63 | { | ||
64 | unsigned int h = spi ^ proto; | ||
65 | switch (family) { | ||
66 | case AF_INET: | ||
67 | h ^= __xfrm4_addr_hash(daddr); | ||
68 | break; | ||
69 | case AF_INET6: | ||
70 | h ^= __xfrm6_addr_hash(daddr); | ||
71 | break; | ||
72 | } | ||
73 | return (h ^ (h >> 10) ^ (h >> 20)) & hmask; | ||
74 | } | ||
75 | |||
76 | static inline unsigned int __idx_hash(u32 index, unsigned int hmask) | ||
77 | { | ||
78 | return (index ^ (index >> 8)) & hmask; | ||
79 | } | ||
80 | |||
81 | static inline unsigned int __sel_hash(struct xfrm_selector *sel, unsigned short family, unsigned int hmask) | ||
82 | { | ||
83 | xfrm_address_t *daddr = &sel->daddr; | ||
84 | xfrm_address_t *saddr = &sel->saddr; | ||
85 | unsigned int h = 0; | ||
86 | |||
87 | switch (family) { | ||
88 | case AF_INET: | ||
89 | if (sel->prefixlen_d != 32 || | ||
90 | sel->prefixlen_s != 32) | ||
91 | return hmask + 1; | ||
92 | |||
93 | h = __xfrm4_daddr_saddr_hash(daddr, saddr); | ||
94 | break; | ||
95 | |||
96 | case AF_INET6: | ||
97 | if (sel->prefixlen_d != 128 || | ||
98 | sel->prefixlen_s != 128) | ||
99 | return hmask + 1; | ||
100 | |||
101 | h = __xfrm6_daddr_saddr_hash(daddr, saddr); | ||
102 | break; | ||
103 | }; | ||
104 | h ^= (h >> 16); | ||
105 | return h & hmask; | ||
106 | } | ||
107 | |||
108 | static inline unsigned int __addr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, unsigned int hmask) | ||
109 | { | ||
110 | unsigned int h = 0; | ||
111 | |||
112 | switch (family) { | ||
113 | case AF_INET: | ||
114 | h = __xfrm4_daddr_saddr_hash(daddr, saddr); | ||
115 | break; | ||
116 | |||
117 | case AF_INET6: | ||
118 | h = __xfrm6_daddr_saddr_hash(daddr, saddr); | ||
119 | break; | ||
120 | }; | ||
121 | h ^= (h >> 16); | ||
122 | return h & hmask; | ||
123 | } | ||
124 | |||
125 | extern struct hlist_head *xfrm_hash_alloc(unsigned int sz); | ||
126 | extern void xfrm_hash_free(struct hlist_head *n, unsigned int sz); | ||
127 | |||
128 | #endif /* _XFRM_HASH_H */ | ||