Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0 */
2 : : #ifndef _XFRM_HASH_H
3 : : #define _XFRM_HASH_H
4 : :
5 : : #include <linux/xfrm.h>
6 : : #include <linux/socket.h>
7 : : #include <linux/jhash.h>
8 : :
9 : : static inline unsigned int __xfrm4_addr_hash(const xfrm_address_t *addr)
10 : : {
11 : 0 : return ntohl(addr->a4);
12 : : }
13 : :
14 : : static inline unsigned int __xfrm6_addr_hash(const xfrm_address_t *addr)
15 : : {
16 : 0 : return jhash2((__force u32 *)addr->a6, 4, 0);
17 : : }
18 : :
19 : : static inline unsigned int __xfrm4_daddr_saddr_hash(const xfrm_address_t *daddr,
20 : : const xfrm_address_t *saddr)
21 : : {
22 : 0 : u32 sum = (__force u32)daddr->a4 + (__force u32)saddr->a4;
23 : 0 : return ntohl((__force __be32)sum);
24 : : }
25 : :
26 : 0 : static inline unsigned int __xfrm6_daddr_saddr_hash(const xfrm_address_t *daddr,
27 : : const xfrm_address_t *saddr)
28 : : {
29 : 0 : return __xfrm6_addr_hash(daddr) ^ __xfrm6_addr_hash(saddr);
30 : : }
31 : :
32 : : static inline u32 __bits2mask32(__u8 bits)
33 : : {
34 : : u32 mask32 = 0xffffffff;
35 : :
36 [ # # # # ]: 0 : if (bits == 0)
37 : : mask32 = 0;
38 [ # # # # ]: 0 : else if (bits < 32)
39 : 0 : mask32 <<= (32 - bits);
40 : :
41 : : return mask32;
42 : : }
43 : :
44 : 0 : static inline unsigned int __xfrm4_dpref_spref_hash(const xfrm_address_t *daddr,
45 : : const xfrm_address_t *saddr,
46 : : __u8 dbits,
47 : : __u8 sbits)
48 : : {
49 : 0 : return jhash_2words(ntohl(daddr->a4) & __bits2mask32(dbits),
50 : 0 : ntohl(saddr->a4) & __bits2mask32(sbits),
51 : : 0);
52 : : }
53 : :
54 : 0 : static inline unsigned int __xfrm6_pref_hash(const xfrm_address_t *addr,
55 : : __u8 prefixlen)
56 : : {
57 : : unsigned int pdw;
58 : : unsigned int pbi;
59 : : u32 initval = 0;
60 : :
61 : 0 : pdw = prefixlen >> 5; /* num of whole u32 in prefix */
62 : 0 : pbi = prefixlen & 0x1f; /* num of bits in incomplete u32 in prefix */
63 : :
64 [ # # ]: 0 : if (pbi) {
65 : : __be32 mask;
66 : :
67 : 0 : mask = htonl((0xffffffff) << (32 - pbi));
68 : :
69 : 0 : initval = (__force u32)(addr->a6[pdw] & mask);
70 : : }
71 : :
72 : 0 : return jhash2((__force u32 *)addr->a6, pdw, initval);
73 : : }
74 : :
75 : : static inline unsigned int __xfrm6_dpref_spref_hash(const xfrm_address_t *daddr,
76 : : const xfrm_address_t *saddr,
77 : : __u8 dbits,
78 : : __u8 sbits)
79 : : {
80 : 0 : return __xfrm6_pref_hash(daddr, dbits) ^
81 : 0 : __xfrm6_pref_hash(saddr, sbits);
82 : : }
83 : :
84 : 0 : static inline unsigned int __xfrm_dst_hash(const xfrm_address_t *daddr,
85 : : const xfrm_address_t *saddr,
86 : : u32 reqid, unsigned short family,
87 : : unsigned int hmask)
88 : : {
89 : 0 : unsigned int h = family ^ reqid;
90 [ # # # ]: 0 : switch (family) {
91 : : case AF_INET:
92 : 0 : h ^= __xfrm4_daddr_saddr_hash(daddr, saddr);
93 : 0 : break;
94 : : case AF_INET6:
95 : 0 : h ^= __xfrm6_daddr_saddr_hash(daddr, saddr);
96 : 0 : break;
97 : : }
98 : 0 : return (h ^ (h >> 16)) & hmask;
99 : : }
100 : :
101 : 0 : static inline unsigned int __xfrm_src_hash(const xfrm_address_t *daddr,
102 : : const xfrm_address_t *saddr,
103 : : unsigned short family,
104 : : unsigned int hmask)
105 : : {
106 : 0 : unsigned int h = family;
107 [ # # # ]: 0 : switch (family) {
108 : : case AF_INET:
109 : 0 : h ^= __xfrm4_daddr_saddr_hash(daddr, saddr);
110 : 0 : break;
111 : : case AF_INET6:
112 : 0 : h ^= __xfrm6_daddr_saddr_hash(daddr, saddr);
113 : 0 : break;
114 : : }
115 : 0 : return (h ^ (h >> 16)) & hmask;
116 : : }
117 : :
118 : : static inline unsigned int
119 : 0 : __xfrm_spi_hash(const xfrm_address_t *daddr, __be32 spi, u8 proto,
120 : : unsigned short family, unsigned int hmask)
121 : : {
122 : 0 : unsigned int h = (__force u32)spi ^ proto;
123 [ # # # ]: 0 : switch (family) {
124 : : case AF_INET:
125 : 0 : h ^= __xfrm4_addr_hash(daddr);
126 : 0 : break;
127 : : case AF_INET6:
128 : 0 : h ^= __xfrm6_addr_hash(daddr);
129 : 0 : break;
130 : : }
131 : 0 : return (h ^ (h >> 10) ^ (h >> 20)) & hmask;
132 : : }
133 : :
134 : : static inline unsigned int __idx_hash(u32 index, unsigned int hmask)
135 : : {
136 : 0 : return (index ^ (index >> 8)) & hmask;
137 : : }
138 : :
139 : 0 : static inline unsigned int __sel_hash(const struct xfrm_selector *sel,
140 : : unsigned short family, unsigned int hmask,
141 : : u8 dbits, u8 sbits)
142 : : {
143 : 0 : const xfrm_address_t *daddr = &sel->daddr;
144 : 0 : const xfrm_address_t *saddr = &sel->saddr;
145 : : unsigned int h = 0;
146 : :
147 [ # # # ]: 0 : switch (family) {
148 : : case AF_INET:
149 [ # # # # ]: 0 : if (sel->prefixlen_d < dbits ||
150 : 0 : sel->prefixlen_s < sbits)
151 : 0 : return hmask + 1;
152 : :
153 : 0 : h = __xfrm4_dpref_spref_hash(daddr, saddr, dbits, sbits);
154 : 0 : break;
155 : :
156 : : case AF_INET6:
157 [ # # # # ]: 0 : if (sel->prefixlen_d < dbits ||
158 : 0 : sel->prefixlen_s < sbits)
159 : 0 : return hmask + 1;
160 : :
161 : : h = __xfrm6_dpref_spref_hash(daddr, saddr, dbits, sbits);
162 : 0 : break;
163 : : }
164 : 0 : h ^= (h >> 16);
165 : 0 : return h & hmask;
166 : : }
167 : :
168 : 0 : static inline unsigned int __addr_hash(const xfrm_address_t *daddr,
169 : : const xfrm_address_t *saddr,
170 : : unsigned short family,
171 : : unsigned int hmask,
172 : : u8 dbits, u8 sbits)
173 : : {
174 : : unsigned int h = 0;
175 : :
176 [ # # # ]: 0 : switch (family) {
177 : : case AF_INET:
178 : 0 : h = __xfrm4_dpref_spref_hash(daddr, saddr, dbits, sbits);
179 : 0 : break;
180 : :
181 : : case AF_INET6:
182 : : h = __xfrm6_dpref_spref_hash(daddr, saddr, dbits, sbits);
183 : 0 : break;
184 : : }
185 : 0 : h ^= (h >> 16);
186 : 0 : return h & hmask;
187 : : }
188 : :
189 : : struct hlist_head *xfrm_hash_alloc(unsigned int sz);
190 : : void xfrm_hash_free(struct hlist_head *n, unsigned int sz);
191 : :
192 : : #endif /* _XFRM_HASH_H */
|