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 */