176404edcSAsim Jamshed /*
276404edcSAsim Jamshed Borrowed XXH32 and XXH64 implementation from xxHash project
376404edcSAsim Jamshed
476404edcSAsim Jamshed Added Copyright notice just above the function definition
576404edcSAsim Jamshed
676404edcSAsim Jamshed TODO 1 : We might wanna implement our version of xxh for copyright reason
776404edcSAsim Jamshed TODO 2 : We might wanna gather all copyright notice and create a single file.
876404edcSAsim Jamshed */
976404edcSAsim Jamshed
1076404edcSAsim Jamshed
1176404edcSAsim Jamshed
1276404edcSAsim Jamshed #include <stdint.h>
1376404edcSAsim Jamshed #include <netinet/in.h>
1476404edcSAsim Jamshed #include <arpa/inet.h>
1576404edcSAsim Jamshed #include <string.h>
1676404edcSAsim Jamshed #include <ctype.h>
1776404edcSAsim Jamshed #include <mtcp_util.h>
18c6a5549bSAsim Jamshed #include <limits.h>
19c6a5549bSAsim Jamshed #include <stdio.h>
20c6a5549bSAsim Jamshed #include <errno.h>
21c6a5549bSAsim Jamshed #include <stdlib.h>
2276404edcSAsim Jamshed
2376404edcSAsim Jamshed /*-------------------------------------------------------------*/
248c9e1184SAsim Jamshed extern int
258c9e1184SAsim Jamshed FetchEndianType();
268c9e1184SAsim Jamshed /*-------------------------------------------------------------*/
2776404edcSAsim Jamshed static void
BuildKeyCache(uint32_t * cache,int cache_len)2876404edcSAsim Jamshed BuildKeyCache(uint32_t *cache, int cache_len)
2976404edcSAsim Jamshed {
3076404edcSAsim Jamshed #ifndef NBBY
3176404edcSAsim Jamshed #define NBBY 8 /* number of bits per byte */
3276404edcSAsim Jamshed #endif
3376404edcSAsim Jamshed
34522d5c66SAsim Jamshed /* Both of DPDK and Netmap uses this key for hash calculation.
3576404edcSAsim Jamshed * Do not change any single bit of this key. */
3676404edcSAsim Jamshed static const uint8_t key[] = {
3776404edcSAsim Jamshed 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
3876404edcSAsim Jamshed 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
3976404edcSAsim Jamshed 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
4076404edcSAsim Jamshed 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
4176404edcSAsim Jamshed 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05
4276404edcSAsim Jamshed };
4376404edcSAsim Jamshed
4476404edcSAsim Jamshed uint32_t result = (((uint32_t)key[0]) << 24) |
4576404edcSAsim Jamshed (((uint32_t)key[1]) << 16) |
4676404edcSAsim Jamshed (((uint32_t)key[2]) << 8) | ((uint32_t)key[3]);
4776404edcSAsim Jamshed uint32_t idx = 32;
4876404edcSAsim Jamshed int i;
4976404edcSAsim Jamshed
5076404edcSAsim Jamshed for (i = 0; i < cache_len; i++, idx++) {
5176404edcSAsim Jamshed uint8_t shift = (idx % NBBY);
5276404edcSAsim Jamshed uint32_t bit;
5376404edcSAsim Jamshed
5476404edcSAsim Jamshed cache[i] = result;
5576404edcSAsim Jamshed bit = ((key[idx/NBBY] << shift) & 0x80) ? 1 : 0;
5676404edcSAsim Jamshed result = ((result << 1) | bit);
5776404edcSAsim Jamshed }
5876404edcSAsim Jamshed
5976404edcSAsim Jamshed }
6076404edcSAsim Jamshed /*-------------------------------------------------------------*/
6176404edcSAsim Jamshed uint32_t
GetRSSHash(in_addr_t sip,in_addr_t dip,in_port_t sp,in_port_t dp)6276404edcSAsim Jamshed GetRSSHash(in_addr_t sip, in_addr_t dip, in_port_t sp, in_port_t dp)
6376404edcSAsim Jamshed {
6476404edcSAsim Jamshed #define MSB32 0x80000000
6576404edcSAsim Jamshed #define MSB16 0x8000
6676404edcSAsim Jamshed #define KEY_CACHE_LEN 96
6776404edcSAsim Jamshed
6876404edcSAsim Jamshed uint32_t res = 0;
6976404edcSAsim Jamshed int i;
7076404edcSAsim Jamshed static int first = 1;
7176404edcSAsim Jamshed static uint32_t key_cache[KEY_CACHE_LEN] = {0};
7276404edcSAsim Jamshed
7376404edcSAsim Jamshed if (first) {
7476404edcSAsim Jamshed BuildKeyCache(key_cache, KEY_CACHE_LEN);
7576404edcSAsim Jamshed first = 0;
7676404edcSAsim Jamshed }
7776404edcSAsim Jamshed
7876404edcSAsim Jamshed for (i = 0; i < 32; i++) {
7976404edcSAsim Jamshed if (sip & MSB32)
8076404edcSAsim Jamshed res ^= key_cache[i];
8176404edcSAsim Jamshed sip <<= 1;
8276404edcSAsim Jamshed }
8376404edcSAsim Jamshed for (i = 0; i < 32; i++) {
8476404edcSAsim Jamshed if (dip & MSB32)
8576404edcSAsim Jamshed res ^= key_cache[32+i];
8676404edcSAsim Jamshed dip <<= 1;
8776404edcSAsim Jamshed }
8876404edcSAsim Jamshed for (i = 0; i < 16; i++) {
8976404edcSAsim Jamshed if (sp & MSB16)
9076404edcSAsim Jamshed res ^= key_cache[64+i];
9176404edcSAsim Jamshed sp <<= 1;
9276404edcSAsim Jamshed }
9376404edcSAsim Jamshed for (i = 0; i < 16; i++) {
9476404edcSAsim Jamshed if (dp & MSB16)
9576404edcSAsim Jamshed res ^= key_cache[80+i];
9676404edcSAsim Jamshed dp <<= 1;
9776404edcSAsim Jamshed }
9876404edcSAsim Jamshed return res;
9976404edcSAsim Jamshed }
10076404edcSAsim Jamshed /*-------------------------------------------------------------------*/
10176404edcSAsim Jamshed /* RSS redirection table is in the little endian byte order (intel) */
10276404edcSAsim Jamshed /* */
10376404edcSAsim Jamshed /* idx: 0 1 2 3 | 4 5 6 7 | 8 9 10 11 | 12 13 14 15 | 16 17 18 19 ...*/
10476404edcSAsim Jamshed /* val: 3 2 1 0 | 7 6 5 4 | 11 10 9 8 | 15 14 13 12 | 19 18 17 16 ...*/
10576404edcSAsim Jamshed /* qid = val % num_queues */
10676404edcSAsim Jamshed /*-------------------------------------------------------------------*/
107*d88f3b1dSYoungGyoun /*
108*d88f3b1dSYoungGyoun * ixgbe (e.g., X520) : (Rx queue #) = (7 LS bits of RSS hash) mod N
109*d88f3b1dSYoungGyoun * i40e (e.g., XL710) : (Rx queue #) = (9 LS bits of RSS hash) mod N
110*d88f3b1dSYoungGyoun */
111*d88f3b1dSYoungGyoun /*-------------------------------------------------------------------*/
112*d88f3b1dSYoungGyoun #define RSS_BIT_MASK_IXGBE 0x0000007F
113*d88f3b1dSYoungGyoun #define RSS_BIT_MASK_I40E 0x000001FF
11476404edcSAsim Jamshed int
GetRSSCPUCore(in_addr_t sip,in_addr_t dip,in_port_t sp,in_port_t dp,int num_queues)11576404edcSAsim Jamshed GetRSSCPUCore(in_addr_t sip, in_addr_t dip,
116*d88f3b1dSYoungGyoun in_port_t sp, in_port_t dp, int num_queues)
11776404edcSAsim Jamshed {
118*d88f3b1dSYoungGyoun uint32_t masked;
1198c9e1184SAsim Jamshed int endian_type = FetchEndianType();
12076404edcSAsim Jamshed
121b88bd7d2SAsim Jamshed if (endian_type) {
122*d88f3b1dSYoungGyoun masked = GetRSSHash(sip, dip, sp, dp) & RSS_BIT_MASK_I40E;
12376404edcSAsim Jamshed static const uint32_t off[4] = {3, 1, -1, -3};
12476404edcSAsim Jamshed masked += off[masked & 0x3];
125b88bd7d2SAsim Jamshed }
126*d88f3b1dSYoungGyoun else
127*d88f3b1dSYoungGyoun masked = GetRSSHash(sip, dip, sp, dp) & RSS_BIT_MASK_IXGBE;
128b88bd7d2SAsim Jamshed
12976404edcSAsim Jamshed return (masked % num_queues);
13076404edcSAsim Jamshed
13176404edcSAsim Jamshed }
13276404edcSAsim Jamshed /*-------------------------------------------------------------*/
13376404edcSAsim Jamshed int
mystrtol(const char * nptr,int base)134c6a5549bSAsim Jamshed mystrtol(const char *nptr, int base)
135c6a5549bSAsim Jamshed {
136c6a5549bSAsim Jamshed int rval;
137c6a5549bSAsim Jamshed char *endptr;
138c6a5549bSAsim Jamshed
139b88bd7d2SAsim Jamshed errno = 0;
140c6a5549bSAsim Jamshed rval = strtol(nptr, &endptr, 10);
141c6a5549bSAsim Jamshed /* check for strtol errors */
142c6a5549bSAsim Jamshed if ((errno == ERANGE && (rval == LONG_MAX ||
143c6a5549bSAsim Jamshed rval == LONG_MIN))
144c6a5549bSAsim Jamshed || (errno != 0 && rval == 0)) {
145c6a5549bSAsim Jamshed perror("strtol");
146c6a5549bSAsim Jamshed exit(EXIT_FAILURE);
147c6a5549bSAsim Jamshed }
148c6a5549bSAsim Jamshed if (endptr == nptr) {
149c6a5549bSAsim Jamshed fprintf(stderr, "Parsing strtol error!\n");
150c6a5549bSAsim Jamshed exit(EXIT_FAILURE);
151c6a5549bSAsim Jamshed }
152c6a5549bSAsim Jamshed
153c6a5549bSAsim Jamshed return rval;
154c6a5549bSAsim Jamshed }
155c6a5549bSAsim Jamshed /*---------------------------------------------------------------*/
156c6a5549bSAsim Jamshed int
StrToArgs(char * str,int * argc,char ** argv,int max_argc)15776404edcSAsim Jamshed StrToArgs(char *str, int *argc, char **argv, int max_argc)
15876404edcSAsim Jamshed {
15976404edcSAsim Jamshed
16076404edcSAsim Jamshed uint8_t single_quotes;
16176404edcSAsim Jamshed uint8_t double_quotes;
16276404edcSAsim Jamshed uint8_t delim;
16376404edcSAsim Jamshed
16476404edcSAsim Jamshed single_quotes = 0;
16576404edcSAsim Jamshed double_quotes = 0;
16676404edcSAsim Jamshed delim = 1;
16776404edcSAsim Jamshed
16876404edcSAsim Jamshed *argc = 0;
16976404edcSAsim Jamshed
17076404edcSAsim Jamshed int i;
17176404edcSAsim Jamshed int len = strlen(str);
17276404edcSAsim Jamshed for (i = 0; i < len; i++) {
17376404edcSAsim Jamshed
17476404edcSAsim Jamshed if (str[i] == '\'') {
17576404edcSAsim Jamshed if (single_quotes)
17676404edcSAsim Jamshed str[i] = '\0';
17776404edcSAsim Jamshed else
17876404edcSAsim Jamshed i++;
17976404edcSAsim Jamshed single_quotes = !single_quotes;
18076404edcSAsim Jamshed goto __non_space;
18176404edcSAsim Jamshed } else if (str[i] == '\"') {
18276404edcSAsim Jamshed if (double_quotes)
18376404edcSAsim Jamshed str[i] = '\0';
18476404edcSAsim Jamshed else
18576404edcSAsim Jamshed i++;
18676404edcSAsim Jamshed double_quotes = !double_quotes;
18776404edcSAsim Jamshed goto __non_space;
18876404edcSAsim Jamshed }
18976404edcSAsim Jamshed
19076404edcSAsim Jamshed if (single_quotes || double_quotes)
19176404edcSAsim Jamshed continue;
19276404edcSAsim Jamshed
19376404edcSAsim Jamshed if (isspace(str[i])) {
19476404edcSAsim Jamshed delim = 1;
19576404edcSAsim Jamshed str[i] = '\0';
19676404edcSAsim Jamshed continue;
19776404edcSAsim Jamshed }
19876404edcSAsim Jamshed __non_space:
19976404edcSAsim Jamshed if (delim == 1) {
20076404edcSAsim Jamshed delim = 0;
20176404edcSAsim Jamshed argv[(*argc)++] = &str[i];
20276404edcSAsim Jamshed if (*argc > max_argc)
20376404edcSAsim Jamshed break;
20476404edcSAsim Jamshed }
20576404edcSAsim Jamshed }
20676404edcSAsim Jamshed
20776404edcSAsim Jamshed argv[*argc] = NULL;
20876404edcSAsim Jamshed
20976404edcSAsim Jamshed return 0;
21076404edcSAsim Jamshed }
21176404edcSAsim Jamshed
21276404edcSAsim Jamshed /*
21376404edcSAsim Jamshed xxHash - Fast Hash algorithm
21476404edcSAsim Jamshed Copyright (C) 2012-2015, Yann Collet
21576404edcSAsim Jamshed
21676404edcSAsim Jamshed BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
21776404edcSAsim Jamshed
21876404edcSAsim Jamshed Redistribution and use in source and binary forms, with or without
21976404edcSAsim Jamshed modification, are permitted provided that the following conditions are
22076404edcSAsim Jamshed met:
22176404edcSAsim Jamshed
22276404edcSAsim Jamshed * Redistributions of source code must retain the above copyright
22376404edcSAsim Jamshed notice, this list of conditions and the following disclaimer.
22476404edcSAsim Jamshed * Redistributions in binary form must reproduce the above
22576404edcSAsim Jamshed copyright notice, this list of conditions and the following disclaimer
22676404edcSAsim Jamshed in the documentation and/or other materials provided with the
22776404edcSAsim Jamshed distribution.
22876404edcSAsim Jamshed
22976404edcSAsim Jamshed THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23076404edcSAsim Jamshed "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23176404edcSAsim Jamshed LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23276404edcSAsim Jamshed A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23376404edcSAsim Jamshed OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23476404edcSAsim Jamshed SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23576404edcSAsim Jamshed LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23676404edcSAsim Jamshed DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23776404edcSAsim Jamshed THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23876404edcSAsim Jamshed (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23976404edcSAsim Jamshed OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24076404edcSAsim Jamshed
24176404edcSAsim Jamshed You can contact the author at :
24276404edcSAsim Jamshed - xxHash source repository : https://github.com/Cyan4973/xxHash
24376404edcSAsim Jamshed */
24476404edcSAsim Jamshed
24576404edcSAsim Jamshed
24676404edcSAsim Jamshed
24776404edcSAsim Jamshed
24876404edcSAsim Jamshed /**************************************
24976404edcSAsim Jamshed * Tuning parameters
25076404edcSAsim Jamshed **************************************/
25176404edcSAsim Jamshed /* Unaligned memory access is automatically enabled for "common" CPU, such as x86.
25276404edcSAsim Jamshed * For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected.
25376404edcSAsim Jamshed * If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance.
25476404edcSAsim Jamshed * You can also enable this parameter if you know your input data will always be aligned (boundaries of 4, for U32).
25576404edcSAsim Jamshed */
25676404edcSAsim Jamshed #if defined(__ARM_FEATURE_UNALIGNED) || defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
25776404edcSAsim Jamshed # define XXH_USE_UNALIGNED_ACCESS 1
25876404edcSAsim Jamshed #endif
25976404edcSAsim Jamshed
26076404edcSAsim Jamshed /* XXH_ACCEPT_NULL_INPUT_POINTER :
26176404edcSAsim Jamshed * If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer.
26276404edcSAsim Jamshed * When this option is enabled, xxHash output for null input pointers will be the same as a null-length input.
26376404edcSAsim Jamshed * By default, this option is disabled. To enable it, uncomment below define :
26476404edcSAsim Jamshed */
26576404edcSAsim Jamshed /* #define XXH_ACCEPT_NULL_INPUT_POINTER 1 */
26676404edcSAsim Jamshed
26776404edcSAsim Jamshed /* XXH_FORCE_NATIVE_FORMAT :
26876404edcSAsim Jamshed * By default, xxHash library provides endian-independant Hash values, based on little-endian convention.
26976404edcSAsim Jamshed * Results are therefore identical for little-endian and big-endian CPU.
27076404edcSAsim Jamshed * This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
27176404edcSAsim Jamshed * Should endian-independance be of no importance for your application, you may set the #define below to 1.
27276404edcSAsim Jamshed * It will improve speed for Big-endian CPU.
27376404edcSAsim Jamshed * This option has no impact on Little_Endian CPU.
27476404edcSAsim Jamshed */
27576404edcSAsim Jamshed #define XXH_FORCE_NATIVE_FORMAT 0
27676404edcSAsim Jamshed
27776404edcSAsim Jamshed
27876404edcSAsim Jamshed /**************************************
27976404edcSAsim Jamshed * Compiler Specific Options
28076404edcSAsim Jamshed ***************************************/
28176404edcSAsim Jamshed #ifdef _MSC_VER /* Visual Studio */
28276404edcSAsim Jamshed # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
28376404edcSAsim Jamshed # define FORCE_INLINE static __forceinline
28476404edcSAsim Jamshed #else
28576404edcSAsim Jamshed # if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
28676404edcSAsim Jamshed # ifdef __GNUC__
28776404edcSAsim Jamshed # define FORCE_INLINE static inline __attribute__((always_inline))
28876404edcSAsim Jamshed # else
28976404edcSAsim Jamshed # define FORCE_INLINE static inline
29076404edcSAsim Jamshed # endif
29176404edcSAsim Jamshed # else
29276404edcSAsim Jamshed # define FORCE_INLINE static
29376404edcSAsim Jamshed # endif /* __STDC_VERSION__ */
29476404edcSAsim Jamshed #endif
29576404edcSAsim Jamshed
29676404edcSAsim Jamshed
29776404edcSAsim Jamshed /**************************************
29876404edcSAsim Jamshed * Basic Types
29976404edcSAsim Jamshed ***************************************/
30076404edcSAsim Jamshed #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
30176404edcSAsim Jamshed # include <stdint.h>
30276404edcSAsim Jamshed typedef uint8_t BYTE;
30376404edcSAsim Jamshed typedef uint16_t U16;
30476404edcSAsim Jamshed typedef uint32_t U32;
30576404edcSAsim Jamshed typedef int32_t S32;
30676404edcSAsim Jamshed typedef uint64_t U64;
30776404edcSAsim Jamshed #else
30876404edcSAsim Jamshed typedef unsigned char BYTE;
30976404edcSAsim Jamshed typedef unsigned short U16;
31076404edcSAsim Jamshed typedef unsigned int U32;
31176404edcSAsim Jamshed typedef signed int S32;
31276404edcSAsim Jamshed typedef unsigned long long U64;
31376404edcSAsim Jamshed #endif
31476404edcSAsim Jamshed
XXH_read32(const void * memPtr)31576404edcSAsim Jamshed static U32 XXH_read32(const void* memPtr)
31676404edcSAsim Jamshed {
31776404edcSAsim Jamshed U32 val32;
31876404edcSAsim Jamshed memcpy(&val32, memPtr, 4);
31976404edcSAsim Jamshed return val32;
32076404edcSAsim Jamshed }
32176404edcSAsim Jamshed
XXH_read64(const void * memPtr)32276404edcSAsim Jamshed static U64 XXH_read64(const void* memPtr)
32376404edcSAsim Jamshed {
32476404edcSAsim Jamshed U64 val64;
32576404edcSAsim Jamshed memcpy(&val64, memPtr, 8);
32676404edcSAsim Jamshed return val64;
32776404edcSAsim Jamshed }
32876404edcSAsim Jamshed
32976404edcSAsim Jamshed
33076404edcSAsim Jamshed
33176404edcSAsim Jamshed /******************************************
33276404edcSAsim Jamshed * Compiler-specific Functions and Macros
33376404edcSAsim Jamshed ******************************************/
33476404edcSAsim Jamshed #define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
33576404edcSAsim Jamshed
33676404edcSAsim Jamshed /* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */
33776404edcSAsim Jamshed #if defined(_MSC_VER)
33876404edcSAsim Jamshed # define XXH_rotl32(x,r) _rotl(x,r)
33976404edcSAsim Jamshed # define XXH_rotl64(x,r) _rotl64(x,r)
34076404edcSAsim Jamshed #else
34176404edcSAsim Jamshed # define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
34276404edcSAsim Jamshed # define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r)))
34376404edcSAsim Jamshed #endif
34476404edcSAsim Jamshed
34576404edcSAsim Jamshed #if defined(_MSC_VER) /* Visual Studio */
34676404edcSAsim Jamshed # define XXH_swap32 _byteswap_ulong
34776404edcSAsim Jamshed # define XXH_swap64 _byteswap_uint64
34876404edcSAsim Jamshed #elif GCC_VERSION >= 403
34976404edcSAsim Jamshed # define XXH_swap32 __builtin_bswap32
35076404edcSAsim Jamshed # define XXH_swap64 __builtin_bswap64
35176404edcSAsim Jamshed #else
XXH_swap32(U32 x)35276404edcSAsim Jamshed static U32 XXH_swap32 (U32 x)
35376404edcSAsim Jamshed {
35476404edcSAsim Jamshed return ((x << 24) & 0xff000000 ) |
35576404edcSAsim Jamshed ((x << 8) & 0x00ff0000 ) |
35676404edcSAsim Jamshed ((x >> 8) & 0x0000ff00 ) |
35776404edcSAsim Jamshed ((x >> 24) & 0x000000ff );
35876404edcSAsim Jamshed }
XXH_swap64(U64 x)35976404edcSAsim Jamshed static U64 XXH_swap64 (U64 x)
36076404edcSAsim Jamshed {
36176404edcSAsim Jamshed return ((x << 56) & 0xff00000000000000ULL) |
36276404edcSAsim Jamshed ((x << 40) & 0x00ff000000000000ULL) |
36376404edcSAsim Jamshed ((x << 24) & 0x0000ff0000000000ULL) |
36476404edcSAsim Jamshed ((x << 8) & 0x000000ff00000000ULL) |
36576404edcSAsim Jamshed ((x >> 8) & 0x00000000ff000000ULL) |
36676404edcSAsim Jamshed ((x >> 24) & 0x0000000000ff0000ULL) |
36776404edcSAsim Jamshed ((x >> 40) & 0x000000000000ff00ULL) |
36876404edcSAsim Jamshed ((x >> 56) & 0x00000000000000ffULL);
36976404edcSAsim Jamshed }
37076404edcSAsim Jamshed #endif
37176404edcSAsim Jamshed
37276404edcSAsim Jamshed
37376404edcSAsim Jamshed /***************************************
37476404edcSAsim Jamshed * Architecture Macros
37576404edcSAsim Jamshed ***************************************/
37676404edcSAsim Jamshed typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
37776404edcSAsim Jamshed #ifndef XXH_CPU_LITTLE_ENDIAN /* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example using a compiler switch */
37876404edcSAsim Jamshed static const int one = 1;
37976404edcSAsim Jamshed # define XXH_CPU_LITTLE_ENDIAN (*(const char*)(&one))
38076404edcSAsim Jamshed #endif
38176404edcSAsim Jamshed
38276404edcSAsim Jamshed
38376404edcSAsim Jamshed /*****************************
38476404edcSAsim Jamshed * Memory reads
38576404edcSAsim Jamshed *****************************/
38676404edcSAsim Jamshed typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
38776404edcSAsim Jamshed
XXH_readLE32_align(const void * ptr,XXH_endianess endian,XXH_alignment align)38876404edcSAsim Jamshed FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
38976404edcSAsim Jamshed {
39076404edcSAsim Jamshed if (align==XXH_unaligned)
39176404edcSAsim Jamshed return endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr));
39276404edcSAsim Jamshed else
39376404edcSAsim Jamshed return endian==XXH_littleEndian ? *(const U32*)ptr : XXH_swap32(*(const U32*)ptr);
39476404edcSAsim Jamshed }
39576404edcSAsim Jamshed
XXH_readLE64_align(const void * ptr,XXH_endianess endian,XXH_alignment align)39676404edcSAsim Jamshed FORCE_INLINE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
39776404edcSAsim Jamshed {
39876404edcSAsim Jamshed if (align==XXH_unaligned)
39976404edcSAsim Jamshed return endian==XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr));
40076404edcSAsim Jamshed else
40176404edcSAsim Jamshed return endian==XXH_littleEndian ? *(const U64*)ptr : XXH_swap64(*(const U64*)ptr);
40276404edcSAsim Jamshed }
40376404edcSAsim Jamshed
40476404edcSAsim Jamshed /***************************************
40576404edcSAsim Jamshed * Macros
40676404edcSAsim Jamshed ***************************************/
40776404edcSAsim Jamshed #define XXH_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(!!(c)) }; } /* use only *after* variable declarations */
40876404edcSAsim Jamshed
40976404edcSAsim Jamshed
41076404edcSAsim Jamshed /***************************************
41176404edcSAsim Jamshed * Constants
41276404edcSAsim Jamshed ***************************************/
41376404edcSAsim Jamshed #define PRIME32_1 2654435761U
41476404edcSAsim Jamshed #define PRIME32_2 2246822519U
41576404edcSAsim Jamshed #define PRIME32_3 3266489917U
41676404edcSAsim Jamshed #define PRIME32_4 668265263U
41776404edcSAsim Jamshed #define PRIME32_5 374761393U
41876404edcSAsim Jamshed
41976404edcSAsim Jamshed #define PRIME64_1 11400714785074694791ULL
42076404edcSAsim Jamshed #define PRIME64_2 14029467366897019727ULL
42176404edcSAsim Jamshed #define PRIME64_3 1609587929392839161ULL
42276404edcSAsim Jamshed #define PRIME64_4 9650029242287828579ULL
42376404edcSAsim Jamshed #define PRIME64_5 2870177450012600261ULL
42476404edcSAsim Jamshed
42576404edcSAsim Jamshed
42676404edcSAsim Jamshed /*****************************
42776404edcSAsim Jamshed * Simple Hash Functions
42876404edcSAsim Jamshed *****************************/
XXH32_endian_align(const void * input,size_t len,U32 seed,XXH_endianess endian,XXH_alignment align)42976404edcSAsim Jamshed FORCE_INLINE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align)
43076404edcSAsim Jamshed {
43176404edcSAsim Jamshed const BYTE* p = (const BYTE*)input;
43276404edcSAsim Jamshed const BYTE* bEnd = p + len;
43376404edcSAsim Jamshed U32 h32;
43476404edcSAsim Jamshed #define XXH_get32bits(p) XXH_readLE32_align(p, endian, align)
43576404edcSAsim Jamshed
43676404edcSAsim Jamshed #ifdef XXH_ACCEPT_NULL_INPUT_POINTER
43776404edcSAsim Jamshed if (p==NULL)
43876404edcSAsim Jamshed {
43976404edcSAsim Jamshed len=0;
44076404edcSAsim Jamshed bEnd=p=(const BYTE*)(size_t)16;
44176404edcSAsim Jamshed }
44276404edcSAsim Jamshed #endif
44376404edcSAsim Jamshed
44476404edcSAsim Jamshed if (len>=16)
44576404edcSAsim Jamshed {
44676404edcSAsim Jamshed const BYTE* const limit = bEnd - 16;
44776404edcSAsim Jamshed U32 v1 = seed + PRIME32_1 + PRIME32_2;
44876404edcSAsim Jamshed U32 v2 = seed + PRIME32_2;
44976404edcSAsim Jamshed U32 v3 = seed + 0;
45076404edcSAsim Jamshed U32 v4 = seed - PRIME32_1;
45176404edcSAsim Jamshed
45276404edcSAsim Jamshed do
45376404edcSAsim Jamshed {
45476404edcSAsim Jamshed v1 += XXH_get32bits(p) * PRIME32_2;
45576404edcSAsim Jamshed v1 = XXH_rotl32(v1, 13);
45676404edcSAsim Jamshed v1 *= PRIME32_1;
45776404edcSAsim Jamshed p+=4;
45876404edcSAsim Jamshed v2 += XXH_get32bits(p) * PRIME32_2;
45976404edcSAsim Jamshed v2 = XXH_rotl32(v2, 13);
46076404edcSAsim Jamshed v2 *= PRIME32_1;
46176404edcSAsim Jamshed p+=4;
46276404edcSAsim Jamshed v3 += XXH_get32bits(p) * PRIME32_2;
46376404edcSAsim Jamshed v3 = XXH_rotl32(v3, 13);
46476404edcSAsim Jamshed v3 *= PRIME32_1;
46576404edcSAsim Jamshed p+=4;
46676404edcSAsim Jamshed v4 += XXH_get32bits(p) * PRIME32_2;
46776404edcSAsim Jamshed v4 = XXH_rotl32(v4, 13);
46876404edcSAsim Jamshed v4 *= PRIME32_1;
46976404edcSAsim Jamshed p+=4;
47076404edcSAsim Jamshed }
47176404edcSAsim Jamshed while (p<=limit);
47276404edcSAsim Jamshed
47376404edcSAsim Jamshed h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
47476404edcSAsim Jamshed }
47576404edcSAsim Jamshed else
47676404edcSAsim Jamshed {
47776404edcSAsim Jamshed h32 = seed + PRIME32_5;
47876404edcSAsim Jamshed }
47976404edcSAsim Jamshed
48076404edcSAsim Jamshed h32 += (U32) len;
48176404edcSAsim Jamshed
48276404edcSAsim Jamshed while (p+4<=bEnd)
48376404edcSAsim Jamshed {
48476404edcSAsim Jamshed h32 += XXH_get32bits(p) * PRIME32_3;
48576404edcSAsim Jamshed h32 = XXH_rotl32(h32, 17) * PRIME32_4 ;
48676404edcSAsim Jamshed p+=4;
48776404edcSAsim Jamshed }
48876404edcSAsim Jamshed
48976404edcSAsim Jamshed while (p<bEnd)
49076404edcSAsim Jamshed {
49176404edcSAsim Jamshed h32 += (*p) * PRIME32_5;
49276404edcSAsim Jamshed h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
49376404edcSAsim Jamshed p++;
49476404edcSAsim Jamshed }
49576404edcSAsim Jamshed
49676404edcSAsim Jamshed h32 ^= h32 >> 15;
49776404edcSAsim Jamshed h32 *= PRIME32_2;
49876404edcSAsim Jamshed h32 ^= h32 >> 13;
49976404edcSAsim Jamshed h32 *= PRIME32_3;
50076404edcSAsim Jamshed h32 ^= h32 >> 16;
50176404edcSAsim Jamshed
50276404edcSAsim Jamshed return h32;
50376404edcSAsim Jamshed }
50476404edcSAsim Jamshed
50576404edcSAsim Jamshed
XXH32(const void * input,size_t len,unsigned seed)50676404edcSAsim Jamshed unsigned XXH32 (const void* input, size_t len, unsigned seed)
50776404edcSAsim Jamshed {
50876404edcSAsim Jamshed #if 0
50976404edcSAsim Jamshed /* Simple version, good for code maintenance, but unfortunately slow for small inputs */
51076404edcSAsim Jamshed XXH32_state_t state;
51176404edcSAsim Jamshed XXH32_reset(&state, seed);
51276404edcSAsim Jamshed XXH32_update(&state, input, len);
51376404edcSAsim Jamshed return XXH32_digest(&state);
51476404edcSAsim Jamshed #else
51576404edcSAsim Jamshed XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
51676404edcSAsim Jamshed
51776404edcSAsim Jamshed # if !defined(XXH_USE_UNALIGNED_ACCESS)
51876404edcSAsim Jamshed if ((((size_t)input) & 3) == 0) /* Input is 4-bytes aligned, leverage the speed benefit */
51976404edcSAsim Jamshed {
52076404edcSAsim Jamshed if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
52176404edcSAsim Jamshed return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
52276404edcSAsim Jamshed else
52376404edcSAsim Jamshed return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
52476404edcSAsim Jamshed }
52576404edcSAsim Jamshed # endif
52676404edcSAsim Jamshed
52776404edcSAsim Jamshed if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
52876404edcSAsim Jamshed return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
52976404edcSAsim Jamshed else
53076404edcSAsim Jamshed return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
53176404edcSAsim Jamshed #endif
53276404edcSAsim Jamshed }
53376404edcSAsim Jamshed
XXH64_endian_align(const void * input,size_t len,U64 seed,XXH_endianess endian,XXH_alignment align)53476404edcSAsim Jamshed FORCE_INLINE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align)
53576404edcSAsim Jamshed {
53676404edcSAsim Jamshed const BYTE* p = (const BYTE*)input;
53776404edcSAsim Jamshed const BYTE* bEnd = p + len;
53876404edcSAsim Jamshed U64 h64;
53976404edcSAsim Jamshed #define XXH_get64bits(p) XXH_readLE64_align(p, endian, align)
54076404edcSAsim Jamshed
54176404edcSAsim Jamshed #ifdef XXH_ACCEPT_NULL_INPUT_POINTER
54276404edcSAsim Jamshed if (p==NULL)
54376404edcSAsim Jamshed {
54476404edcSAsim Jamshed len=0;
54576404edcSAsim Jamshed bEnd=p=(const BYTE*)(size_t)32;
54676404edcSAsim Jamshed }
54776404edcSAsim Jamshed #endif
54876404edcSAsim Jamshed
54976404edcSAsim Jamshed if (len>=32)
55076404edcSAsim Jamshed {
55176404edcSAsim Jamshed const BYTE* const limit = bEnd - 32;
55276404edcSAsim Jamshed U64 v1 = seed + PRIME64_1 + PRIME64_2;
55376404edcSAsim Jamshed U64 v2 = seed + PRIME64_2;
55476404edcSAsim Jamshed U64 v3 = seed + 0;
55576404edcSAsim Jamshed U64 v4 = seed - PRIME64_1;
55676404edcSAsim Jamshed
55776404edcSAsim Jamshed do
55876404edcSAsim Jamshed {
55976404edcSAsim Jamshed v1 += XXH_get64bits(p) * PRIME64_2;
56076404edcSAsim Jamshed p+=8;
56176404edcSAsim Jamshed v1 = XXH_rotl64(v1, 31);
56276404edcSAsim Jamshed v1 *= PRIME64_1;
56376404edcSAsim Jamshed v2 += XXH_get64bits(p) * PRIME64_2;
56476404edcSAsim Jamshed p+=8;
56576404edcSAsim Jamshed v2 = XXH_rotl64(v2, 31);
56676404edcSAsim Jamshed v2 *= PRIME64_1;
56776404edcSAsim Jamshed v3 += XXH_get64bits(p) * PRIME64_2;
56876404edcSAsim Jamshed p+=8;
56976404edcSAsim Jamshed v3 = XXH_rotl64(v3, 31);
57076404edcSAsim Jamshed v3 *= PRIME64_1;
57176404edcSAsim Jamshed v4 += XXH_get64bits(p) * PRIME64_2;
57276404edcSAsim Jamshed p+=8;
57376404edcSAsim Jamshed v4 = XXH_rotl64(v4, 31);
57476404edcSAsim Jamshed v4 *= PRIME64_1;
57576404edcSAsim Jamshed }
57676404edcSAsim Jamshed while (p<=limit);
57776404edcSAsim Jamshed
57876404edcSAsim Jamshed h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
57976404edcSAsim Jamshed
58076404edcSAsim Jamshed v1 *= PRIME64_2;
58176404edcSAsim Jamshed v1 = XXH_rotl64(v1, 31);
58276404edcSAsim Jamshed v1 *= PRIME64_1;
58376404edcSAsim Jamshed h64 ^= v1;
58476404edcSAsim Jamshed h64 = h64 * PRIME64_1 + PRIME64_4;
58576404edcSAsim Jamshed
58676404edcSAsim Jamshed v2 *= PRIME64_2;
58776404edcSAsim Jamshed v2 = XXH_rotl64(v2, 31);
58876404edcSAsim Jamshed v2 *= PRIME64_1;
58976404edcSAsim Jamshed h64 ^= v2;
59076404edcSAsim Jamshed h64 = h64 * PRIME64_1 + PRIME64_4;
59176404edcSAsim Jamshed
59276404edcSAsim Jamshed v3 *= PRIME64_2;
59376404edcSAsim Jamshed v3 = XXH_rotl64(v3, 31);
59476404edcSAsim Jamshed v3 *= PRIME64_1;
59576404edcSAsim Jamshed h64 ^= v3;
59676404edcSAsim Jamshed h64 = h64 * PRIME64_1 + PRIME64_4;
59776404edcSAsim Jamshed
59876404edcSAsim Jamshed v4 *= PRIME64_2;
59976404edcSAsim Jamshed v4 = XXH_rotl64(v4, 31);
60076404edcSAsim Jamshed v4 *= PRIME64_1;
60176404edcSAsim Jamshed h64 ^= v4;
60276404edcSAsim Jamshed h64 = h64 * PRIME64_1 + PRIME64_4;
60376404edcSAsim Jamshed }
60476404edcSAsim Jamshed else
60576404edcSAsim Jamshed {
60676404edcSAsim Jamshed h64 = seed + PRIME64_5;
60776404edcSAsim Jamshed }
60876404edcSAsim Jamshed
60976404edcSAsim Jamshed h64 += (U64) len;
61076404edcSAsim Jamshed
61176404edcSAsim Jamshed while (p+8<=bEnd)
61276404edcSAsim Jamshed {
61376404edcSAsim Jamshed U64 k1 = XXH_get64bits(p);
61476404edcSAsim Jamshed k1 *= PRIME64_2;
61576404edcSAsim Jamshed k1 = XXH_rotl64(k1,31);
61676404edcSAsim Jamshed k1 *= PRIME64_1;
61776404edcSAsim Jamshed h64 ^= k1;
61876404edcSAsim Jamshed h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
61976404edcSAsim Jamshed p+=8;
62076404edcSAsim Jamshed }
62176404edcSAsim Jamshed
62276404edcSAsim Jamshed if (p+4<=bEnd)
62376404edcSAsim Jamshed {
62476404edcSAsim Jamshed h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1;
62576404edcSAsim Jamshed h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
62676404edcSAsim Jamshed p+=4;
62776404edcSAsim Jamshed }
62876404edcSAsim Jamshed
62976404edcSAsim Jamshed while (p<bEnd)
63076404edcSAsim Jamshed {
63176404edcSAsim Jamshed h64 ^= (*p) * PRIME64_5;
63276404edcSAsim Jamshed h64 = XXH_rotl64(h64, 11) * PRIME64_1;
63376404edcSAsim Jamshed p++;
63476404edcSAsim Jamshed }
63576404edcSAsim Jamshed
63676404edcSAsim Jamshed h64 ^= h64 >> 33;
63776404edcSAsim Jamshed h64 *= PRIME64_2;
63876404edcSAsim Jamshed h64 ^= h64 >> 29;
63976404edcSAsim Jamshed h64 *= PRIME64_3;
64076404edcSAsim Jamshed h64 ^= h64 >> 32;
64176404edcSAsim Jamshed
64276404edcSAsim Jamshed return h64;
64376404edcSAsim Jamshed }
64476404edcSAsim Jamshed
64576404edcSAsim Jamshed
XXH64(const void * input,size_t len,unsigned long long seed)64676404edcSAsim Jamshed unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed)
64776404edcSAsim Jamshed {
64876404edcSAsim Jamshed #if 0
64976404edcSAsim Jamshed /* Simple version, good for code maintenance, but unfortunately slow for small inputs */
65076404edcSAsim Jamshed XXH64_state_t state;
65176404edcSAsim Jamshed XXH64_reset(&state, seed);
65276404edcSAsim Jamshed XXH64_update(&state, input, len);
65376404edcSAsim Jamshed return XXH64_digest(&state);
65476404edcSAsim Jamshed #else
65576404edcSAsim Jamshed XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
65676404edcSAsim Jamshed
65776404edcSAsim Jamshed # if !defined(XXH_USE_UNALIGNED_ACCESS)
65876404edcSAsim Jamshed if ((((size_t)input) & 7)==0) /* Input is aligned, let's leverage the speed advantage */
65976404edcSAsim Jamshed {
66076404edcSAsim Jamshed if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
66176404edcSAsim Jamshed return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
66276404edcSAsim Jamshed else
66376404edcSAsim Jamshed return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
66476404edcSAsim Jamshed }
66576404edcSAsim Jamshed # endif
66676404edcSAsim Jamshed
66776404edcSAsim Jamshed if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
66876404edcSAsim Jamshed return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
66976404edcSAsim Jamshed else
67076404edcSAsim Jamshed return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
67176404edcSAsim Jamshed #endif
67276404edcSAsim Jamshed }
67376404edcSAsim Jamshed
674