1 /* SPDX-License-Identifier: GPL-2.0 */
5 #include <linux/xfrm.h>
6 #include <linux/socket.h>
7 #include <linux/jhash.h>
9 static inline unsigned int __xfrm4_addr_hash(const xfrm_address_t
*addr
)
11 return ntohl(addr
->a4
);
14 static inline unsigned int __xfrm6_addr_hash(const xfrm_address_t
*addr
)
16 return ntohl(addr
->a6
[2] ^ addr
->a6
[3]);
19 static inline unsigned int __xfrm4_daddr_saddr_hash(const xfrm_address_t
*daddr
,
20 const xfrm_address_t
*saddr
)
22 u32 sum
= (__force u32
)daddr
->a4
+ (__force u32
)saddr
->a4
;
23 return ntohl((__force __be32
)sum
);
26 static inline unsigned int __xfrm6_daddr_saddr_hash(const xfrm_address_t
*daddr
,
27 const xfrm_address_t
*saddr
)
29 return ntohl(daddr
->a6
[2] ^ daddr
->a6
[3] ^
30 saddr
->a6
[2] ^ saddr
->a6
[3]);
33 static inline u32
__bits2mask32(__u8 bits
)
35 u32 mask32
= 0xffffffff;
40 mask32
<<= (32 - bits
);
45 static inline unsigned int __xfrm4_dpref_spref_hash(const xfrm_address_t
*daddr
,
46 const xfrm_address_t
*saddr
,
50 return jhash_2words(ntohl(daddr
->a4
) & __bits2mask32(dbits
),
51 ntohl(saddr
->a4
) & __bits2mask32(sbits
),
55 static inline unsigned int __xfrm6_pref_hash(const xfrm_address_t
*addr
,
62 pdw
= prefixlen
>> 5; /* num of whole u32 in prefix */
63 pbi
= prefixlen
& 0x1f; /* num of bits in incomplete u32 in prefix */
68 mask
= htonl((0xffffffff) << (32 - pbi
));
70 initval
= (__force u32
)(addr
->a6
[pdw
] & mask
);
73 return jhash2((__force u32
*)addr
->a6
, pdw
, initval
);
76 static inline unsigned int __xfrm6_dpref_spref_hash(const xfrm_address_t
*daddr
,
77 const xfrm_address_t
*saddr
,
81 return __xfrm6_pref_hash(daddr
, dbits
) ^
82 __xfrm6_pref_hash(saddr
, sbits
);
85 static inline unsigned int __xfrm_dst_hash(const xfrm_address_t
*daddr
,
86 const xfrm_address_t
*saddr
,
87 u32 reqid
, unsigned short family
,
90 unsigned int h
= family
^ reqid
;
93 h
^= __xfrm4_daddr_saddr_hash(daddr
, saddr
);
96 h
^= __xfrm6_daddr_saddr_hash(daddr
, saddr
);
99 return (h
^ (h
>> 16)) & hmask
;
102 static inline unsigned int __xfrm_src_hash(const xfrm_address_t
*daddr
,
103 const xfrm_address_t
*saddr
,
104 unsigned short family
,
107 unsigned int h
= family
;
110 h
^= __xfrm4_daddr_saddr_hash(daddr
, saddr
);
113 h
^= __xfrm6_daddr_saddr_hash(daddr
, saddr
);
116 return (h
^ (h
>> 16)) & hmask
;
119 static inline unsigned int
120 __xfrm_spi_hash(const xfrm_address_t
*daddr
, __be32 spi
, u8 proto
,
121 unsigned short family
, unsigned int hmask
)
123 unsigned int h
= (__force u32
)spi
^ proto
;
126 h
^= __xfrm4_addr_hash(daddr
);
129 h
^= __xfrm6_addr_hash(daddr
);
132 return (h
^ (h
>> 10) ^ (h
>> 20)) & hmask
;
135 static inline unsigned int __idx_hash(u32 index
, unsigned int hmask
)
137 return (index
^ (index
>> 8)) & hmask
;
140 static inline unsigned int __sel_hash(const struct xfrm_selector
*sel
,
141 unsigned short family
, unsigned int hmask
,
144 const xfrm_address_t
*daddr
= &sel
->daddr
;
145 const xfrm_address_t
*saddr
= &sel
->saddr
;
150 if (sel
->prefixlen_d
< dbits
||
151 sel
->prefixlen_s
< sbits
)
154 h
= __xfrm4_dpref_spref_hash(daddr
, saddr
, dbits
, sbits
);
158 if (sel
->prefixlen_d
< dbits
||
159 sel
->prefixlen_s
< sbits
)
162 h
= __xfrm6_dpref_spref_hash(daddr
, saddr
, dbits
, sbits
);
169 static inline unsigned int __addr_hash(const xfrm_address_t
*daddr
,
170 const xfrm_address_t
*saddr
,
171 unsigned short family
,
179 h
= __xfrm4_dpref_spref_hash(daddr
, saddr
, dbits
, sbits
);
183 h
= __xfrm6_dpref_spref_hash(daddr
, saddr
, dbits
, sbits
);
190 struct hlist_head
*xfrm_hash_alloc(unsigned int sz
);
191 void xfrm_hash_free(struct hlist_head
*n
, unsigned int sz
);
193 #endif /* _XFRM_HASH_H */