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 jhash2((__force u32
*)addr
->a6
, 4, 0);
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 __xfrm6_addr_hash(daddr
) ^ __xfrm6_addr_hash(saddr
);
32 static inline u32
__bits2mask32(__u8 bits
)
34 u32 mask32
= 0xffffffff;
39 mask32
<<= (32 - bits
);
44 static inline unsigned int __xfrm4_dpref_spref_hash(const xfrm_address_t
*daddr
,
45 const xfrm_address_t
*saddr
,
49 return jhash_2words(ntohl(daddr
->a4
) & __bits2mask32(dbits
),
50 ntohl(saddr
->a4
) & __bits2mask32(sbits
),
54 static inline unsigned int __xfrm6_pref_hash(const xfrm_address_t
*addr
,
61 pdw
= prefixlen
>> 5; /* num of whole u32 in prefix */
62 pbi
= prefixlen
& 0x1f; /* num of bits in incomplete u32 in prefix */
67 mask
= htonl((0xffffffff) << (32 - pbi
));
69 initval
= (__force u32
)(addr
->a6
[pdw
] & mask
);
72 return jhash2((__force u32
*)addr
->a6
, pdw
, initval
);
75 static inline unsigned int __xfrm6_dpref_spref_hash(const xfrm_address_t
*daddr
,
76 const xfrm_address_t
*saddr
,
80 return __xfrm6_pref_hash(daddr
, dbits
) ^
81 __xfrm6_pref_hash(saddr
, sbits
);
84 static inline unsigned int __xfrm_dst_hash(const xfrm_address_t
*daddr
,
85 const xfrm_address_t
*saddr
,
86 u32 reqid
, unsigned short family
,
89 unsigned int h
= family
^ reqid
;
92 h
^= __xfrm4_daddr_saddr_hash(daddr
, saddr
);
95 h
^= __xfrm6_daddr_saddr_hash(daddr
, saddr
);
98 return (h
^ (h
>> 16)) & hmask
;
101 static inline unsigned int __xfrm_src_hash(const xfrm_address_t
*daddr
,
102 const xfrm_address_t
*saddr
,
103 unsigned short family
,
106 unsigned int h
= family
;
109 h
^= __xfrm4_daddr_saddr_hash(daddr
, saddr
);
112 h
^= __xfrm6_daddr_saddr_hash(daddr
, saddr
);
115 return (h
^ (h
>> 16)) & hmask
;
118 static inline unsigned int
119 __xfrm_spi_hash(const xfrm_address_t
*daddr
, __be32 spi
, u8 proto
,
120 unsigned short family
, unsigned int hmask
)
122 unsigned int h
= (__force u32
)spi
^ proto
;
125 h
^= __xfrm4_addr_hash(daddr
);
128 h
^= __xfrm6_addr_hash(daddr
);
131 return (h
^ (h
>> 10) ^ (h
>> 20)) & hmask
;
134 static inline unsigned int __idx_hash(u32 index
, unsigned int hmask
)
136 return (index
^ (index
>> 8)) & hmask
;
139 static inline unsigned int __sel_hash(const struct xfrm_selector
*sel
,
140 unsigned short family
, unsigned int hmask
,
143 const xfrm_address_t
*daddr
= &sel
->daddr
;
144 const xfrm_address_t
*saddr
= &sel
->saddr
;
149 if (sel
->prefixlen_d
< dbits
||
150 sel
->prefixlen_s
< sbits
)
153 h
= __xfrm4_dpref_spref_hash(daddr
, saddr
, dbits
, sbits
);
157 if (sel
->prefixlen_d
< dbits
||
158 sel
->prefixlen_s
< sbits
)
161 h
= __xfrm6_dpref_spref_hash(daddr
, saddr
, dbits
, sbits
);
168 static inline unsigned int __addr_hash(const xfrm_address_t
*daddr
,
169 const xfrm_address_t
*saddr
,
170 unsigned short family
,
178 h
= __xfrm4_dpref_spref_hash(daddr
, saddr
, dbits
, sbits
);
182 h
= __xfrm6_dpref_spref_hash(daddr
, saddr
, dbits
, sbits
);
189 struct hlist_head
*xfrm_hash_alloc(unsigned int sz
);
190 void xfrm_hash_free(struct hlist_head
*n
, unsigned int sz
);
192 #endif /* _XFRM_HASH_H */