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