0001
0002 #ifndef _XFRM_HASH_H
0003 #define _XFRM_HASH_H
0004
0005 #include <linux/xfrm.h>
0006 #include <linux/socket.h>
0007 #include <linux/jhash.h>
0008
0009 static inline unsigned int __xfrm4_addr_hash(const xfrm_address_t *addr)
0010 {
0011 return ntohl(addr->a4);
0012 }
0013
0014 static inline unsigned int __xfrm6_addr_hash(const xfrm_address_t *addr)
0015 {
0016 return jhash2((__force u32 *)addr->a6, 4, 0);
0017 }
0018
0019 static inline unsigned int __xfrm4_daddr_saddr_hash(const xfrm_address_t *daddr,
0020 const xfrm_address_t *saddr)
0021 {
0022 u32 sum = (__force u32)daddr->a4 + (__force u32)saddr->a4;
0023 return ntohl((__force __be32)sum);
0024 }
0025
0026 static inline unsigned int __xfrm6_daddr_saddr_hash(const xfrm_address_t *daddr,
0027 const xfrm_address_t *saddr)
0028 {
0029 return __xfrm6_addr_hash(daddr) ^ __xfrm6_addr_hash(saddr);
0030 }
0031
0032 static inline u32 __bits2mask32(__u8 bits)
0033 {
0034 u32 mask32 = 0xffffffff;
0035
0036 if (bits == 0)
0037 mask32 = 0;
0038 else if (bits < 32)
0039 mask32 <<= (32 - bits);
0040
0041 return mask32;
0042 }
0043
0044 static inline unsigned int __xfrm4_dpref_spref_hash(const xfrm_address_t *daddr,
0045 const xfrm_address_t *saddr,
0046 __u8 dbits,
0047 __u8 sbits)
0048 {
0049 return jhash_2words(ntohl(daddr->a4) & __bits2mask32(dbits),
0050 ntohl(saddr->a4) & __bits2mask32(sbits),
0051 0);
0052 }
0053
0054 static inline unsigned int __xfrm6_pref_hash(const xfrm_address_t *addr,
0055 __u8 prefixlen)
0056 {
0057 unsigned int pdw;
0058 unsigned int pbi;
0059 u32 initval = 0;
0060
0061 pdw = prefixlen >> 5;
0062 pbi = prefixlen & 0x1f;
0063
0064 if (pbi) {
0065 __be32 mask;
0066
0067 mask = htonl((0xffffffff) << (32 - pbi));
0068
0069 initval = (__force u32)(addr->a6[pdw] & mask);
0070 }
0071
0072 return jhash2((__force u32 *)addr->a6, pdw, initval);
0073 }
0074
0075 static inline unsigned int __xfrm6_dpref_spref_hash(const xfrm_address_t *daddr,
0076 const xfrm_address_t *saddr,
0077 __u8 dbits,
0078 __u8 sbits)
0079 {
0080 return __xfrm6_pref_hash(daddr, dbits) ^
0081 __xfrm6_pref_hash(saddr, sbits);
0082 }
0083
0084 static inline unsigned int __xfrm_dst_hash(const xfrm_address_t *daddr,
0085 const xfrm_address_t *saddr,
0086 u32 reqid, unsigned short family,
0087 unsigned int hmask)
0088 {
0089 unsigned int h = family ^ reqid;
0090 switch (family) {
0091 case AF_INET:
0092 h ^= __xfrm4_daddr_saddr_hash(daddr, saddr);
0093 break;
0094 case AF_INET6:
0095 h ^= __xfrm6_daddr_saddr_hash(daddr, saddr);
0096 break;
0097 }
0098 return (h ^ (h >> 16)) & hmask;
0099 }
0100
0101 static inline unsigned int __xfrm_src_hash(const xfrm_address_t *daddr,
0102 const xfrm_address_t *saddr,
0103 unsigned short family,
0104 unsigned int hmask)
0105 {
0106 unsigned int h = family;
0107 switch (family) {
0108 case AF_INET:
0109 h ^= __xfrm4_daddr_saddr_hash(daddr, saddr);
0110 break;
0111 case AF_INET6:
0112 h ^= __xfrm6_daddr_saddr_hash(daddr, saddr);
0113 break;
0114 }
0115 return (h ^ (h >> 16)) & hmask;
0116 }
0117
0118 static inline unsigned int
0119 __xfrm_spi_hash(const xfrm_address_t *daddr, __be32 spi, u8 proto,
0120 unsigned short family, unsigned int hmask)
0121 {
0122 unsigned int h = (__force u32)spi ^ proto;
0123 switch (family) {
0124 case AF_INET:
0125 h ^= __xfrm4_addr_hash(daddr);
0126 break;
0127 case AF_INET6:
0128 h ^= __xfrm6_addr_hash(daddr);
0129 break;
0130 }
0131 return (h ^ (h >> 10) ^ (h >> 20)) & hmask;
0132 }
0133
0134 static inline unsigned int
0135 __xfrm_seq_hash(u32 seq, unsigned int hmask)
0136 {
0137 unsigned int h = seq;
0138 return (h ^ (h >> 10) ^ (h >> 20)) & hmask;
0139 }
0140
0141 static inline unsigned int __idx_hash(u32 index, unsigned int hmask)
0142 {
0143 return (index ^ (index >> 8)) & hmask;
0144 }
0145
0146 static inline unsigned int __sel_hash(const struct xfrm_selector *sel,
0147 unsigned short family, unsigned int hmask,
0148 u8 dbits, u8 sbits)
0149 {
0150 const xfrm_address_t *daddr = &sel->daddr;
0151 const xfrm_address_t *saddr = &sel->saddr;
0152 unsigned int h = 0;
0153
0154 switch (family) {
0155 case AF_INET:
0156 if (sel->prefixlen_d < dbits ||
0157 sel->prefixlen_s < sbits)
0158 return hmask + 1;
0159
0160 h = __xfrm4_dpref_spref_hash(daddr, saddr, dbits, sbits);
0161 break;
0162
0163 case AF_INET6:
0164 if (sel->prefixlen_d < dbits ||
0165 sel->prefixlen_s < sbits)
0166 return hmask + 1;
0167
0168 h = __xfrm6_dpref_spref_hash(daddr, saddr, dbits, sbits);
0169 break;
0170 }
0171 h ^= (h >> 16);
0172 return h & hmask;
0173 }
0174
0175 static inline unsigned int __addr_hash(const xfrm_address_t *daddr,
0176 const xfrm_address_t *saddr,
0177 unsigned short family,
0178 unsigned int hmask,
0179 u8 dbits, u8 sbits)
0180 {
0181 unsigned int h = 0;
0182
0183 switch (family) {
0184 case AF_INET:
0185 h = __xfrm4_dpref_spref_hash(daddr, saddr, dbits, sbits);
0186 break;
0187
0188 case AF_INET6:
0189 h = __xfrm6_dpref_spref_hash(daddr, saddr, dbits, sbits);
0190 break;
0191 }
0192 h ^= (h >> 16);
0193 return h & hmask;
0194 }
0195
0196 struct hlist_head *xfrm_hash_alloc(unsigned int sz);
0197 void xfrm_hash_free(struct hlist_head *n, unsigned int sz);
0198
0199 #endif