]>
Commit | Line | Data |
---|---|---|
44e36b42 DM |
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 | { | |
0eae88f3 ED |
19 | u32 sum = (__force u32)daddr->a4 + (__force u32)saddr->a4; |
20 | return ntohl((__force __be32)sum); | |
44e36b42 DM |
21 | } |
22 | ||
23 | static inline unsigned int __xfrm6_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) | |
24 | { | |
25 | return ntohl(daddr->a6[2] ^ daddr->a6[3] ^ | |
26 | saddr->a6[2] ^ saddr->a6[3]); | |
27 | } | |
28 | ||
29 | static inline unsigned int __xfrm_dst_hash(xfrm_address_t *daddr, xfrm_address_t *saddr, | |
30 | u32 reqid, unsigned short family, | |
31 | unsigned int hmask) | |
32 | { | |
33 | unsigned int h = family ^ reqid; | |
34 | switch (family) { | |
35 | case AF_INET: | |
36 | h ^= __xfrm4_daddr_saddr_hash(daddr, saddr); | |
37 | break; | |
38 | case AF_INET6: | |
39 | h ^= __xfrm6_daddr_saddr_hash(daddr, saddr); | |
40 | break; | |
41 | } | |
42 | return (h ^ (h >> 16)) & hmask; | |
43 | } | |
44 | ||
667bbcb6 MN |
45 | static inline unsigned __xfrm_src_hash(xfrm_address_t *daddr, |
46 | xfrm_address_t *saddr, | |
44e36b42 DM |
47 | unsigned short family, |
48 | unsigned int hmask) | |
49 | { | |
50 | unsigned int h = family; | |
51 | switch (family) { | |
52 | case AF_INET: | |
667bbcb6 | 53 | h ^= __xfrm4_daddr_saddr_hash(daddr, saddr); |
44e36b42 DM |
54 | break; |
55 | case AF_INET6: | |
667bbcb6 | 56 | h ^= __xfrm6_daddr_saddr_hash(daddr, saddr); |
44e36b42 | 57 | break; |
ccbd6a5a | 58 | } |
44e36b42 DM |
59 | return (h ^ (h >> 16)) & hmask; |
60 | } | |
61 | ||
62 | static inline unsigned int | |
8122adf0 | 63 | __xfrm_spi_hash(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family, |
44e36b42 DM |
64 | unsigned int hmask) |
65 | { | |
8122adf0 | 66 | unsigned int h = (__force u32)spi ^ proto; |
44e36b42 DM |
67 | switch (family) { |
68 | case AF_INET: | |
69 | h ^= __xfrm4_addr_hash(daddr); | |
70 | break; | |
71 | case AF_INET6: | |
72 | h ^= __xfrm6_addr_hash(daddr); | |
73 | break; | |
74 | } | |
75 | return (h ^ (h >> 10) ^ (h >> 20)) & hmask; | |
76 | } | |
77 | ||
78 | static inline unsigned int __idx_hash(u32 index, unsigned int hmask) | |
79 | { | |
80 | return (index ^ (index >> 8)) & hmask; | |
81 | } | |
82 | ||
83 | static inline unsigned int __sel_hash(struct xfrm_selector *sel, unsigned short family, unsigned int hmask) | |
84 | { | |
85 | xfrm_address_t *daddr = &sel->daddr; | |
86 | xfrm_address_t *saddr = &sel->saddr; | |
87 | unsigned int h = 0; | |
88 | ||
89 | switch (family) { | |
90 | case AF_INET: | |
91 | if (sel->prefixlen_d != 32 || | |
92 | sel->prefixlen_s != 32) | |
93 | return hmask + 1; | |
94 | ||
95 | h = __xfrm4_daddr_saddr_hash(daddr, saddr); | |
96 | break; | |
97 | ||
98 | case AF_INET6: | |
99 | if (sel->prefixlen_d != 128 || | |
100 | sel->prefixlen_s != 128) | |
101 | return hmask + 1; | |
102 | ||
103 | h = __xfrm6_daddr_saddr_hash(daddr, saddr); | |
104 | break; | |
ccbd6a5a | 105 | } |
44e36b42 DM |
106 | h ^= (h >> 16); |
107 | return h & hmask; | |
108 | } | |
109 | ||
110 | static inline unsigned int __addr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, unsigned int hmask) | |
111 | { | |
112 | unsigned int h = 0; | |
113 | ||
114 | switch (family) { | |
115 | case AF_INET: | |
116 | h = __xfrm4_daddr_saddr_hash(daddr, saddr); | |
117 | break; | |
118 | ||
119 | case AF_INET6: | |
120 | h = __xfrm6_daddr_saddr_hash(daddr, saddr); | |
121 | break; | |
ccbd6a5a | 122 | } |
44e36b42 DM |
123 | h ^= (h >> 16); |
124 | return h & hmask; | |
125 | } | |
126 | ||
127 | extern struct hlist_head *xfrm_hash_alloc(unsigned int sz); | |
128 | extern void xfrm_hash_free(struct hlist_head *n, unsigned int sz); | |
129 | ||
130 | #endif /* _XFRM_HASH_H */ |