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