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 | { | |
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 */ |