Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
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;     /* num of whole u32 in prefix */
0062     pbi = prefixlen &  0x1f;  /* num of bits in incomplete u32 in prefix */
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 /* _XFRM_HASH_H */