github.com/cilium/cilium@v1.16.2/bpf/lib/jhash.h (about)

     1  /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
     2  /* Copyright (C) 2006 Bob Jenkins <bob_jenkins@burtleburtle.net> */
     3  /* Copyright (C) 2006-2020 Authors of the Linux kernel */
     4  /* Copyright Authors of Cilium */
     5  
     6  #pragma once
     7  
     8  #include <bpf/ctx/ctx.h>
     9  #include <bpf/api.h>
    10  
    11  #define JHASH_INITVAL	0xdeadbeef
    12  
    13  static __always_inline __u32 rol32(__u32 word, __u32 shift)
    14  {
    15  	return (word << shift) | (word >> ((-shift) & 31));
    16  }
    17  
    18  #define __jhash_mix(a, b, c)			\
    19  {						\
    20  	a -= c;  a ^= rol32(c, 4);  c += b;	\
    21  	b -= a;  b ^= rol32(a, 6);  a += c;	\
    22  	c -= b;  c ^= rol32(b, 8);  b += a;	\
    23  	a -= c;  a ^= rol32(c, 16); c += b;	\
    24  	b -= a;  b ^= rol32(a, 19); a += c;	\
    25  	c -= b;  c ^= rol32(b, 4);  b += a;	\
    26  }
    27  
    28  #define __jhash_final(a, b, c)			\
    29  {						\
    30  	c ^= b; c -= rol32(b, 14);		\
    31  	a ^= c; a -= rol32(c, 11);		\
    32  	b ^= a; b -= rol32(a, 25);		\
    33  	c ^= b; c -= rol32(b, 16);		\
    34  	a ^= c; a -= rol32(c, 4);		\
    35  	b ^= a; b -= rol32(a, 14);		\
    36  	c ^= b; c -= rol32(b, 24);		\
    37  }
    38  
    39  static __always_inline __u32 jhash(const void *key, __u32 length,
    40  				   __u32 initval)
    41  {
    42  	const unsigned char *k = key;
    43  	__u32 a, b, c;
    44  
    45  	if (!__builtin_constant_p(length))
    46  		__throw_build_bug();
    47  
    48  	a = b = c = JHASH_INITVAL + length + initval;
    49  
    50  	while (length > 12) {
    51  		a += *(__u32 *)(k);
    52  		b += *(__u32 *)(k + 4);
    53  		c += *(__u32 *)(k + 8);
    54  
    55  		__jhash_mix(a, b, c);
    56  		length -= 12;
    57  		k += 12;
    58  	}
    59  
    60  	switch (length) {
    61  	case 12: c += (__u32)k[11] << 24; fallthrough;
    62  	case 11: c += (__u32)k[10] << 16; fallthrough;
    63  	case 10: c +=  (__u32)k[9] <<  8; fallthrough;
    64  	case 9:  c +=  (__u32)k[8];       fallthrough;
    65  	case 8:  b +=  (__u32)k[7] << 24; fallthrough;
    66  	case 7:  b +=  (__u32)k[6] << 16; fallthrough;
    67  	case 6:  b +=  (__u32)k[5] <<  8; fallthrough;
    68  	case 5:  b +=  (__u32)k[4];       fallthrough;
    69  	case 4:  a +=  (__u32)k[3] << 24; fallthrough;
    70  	case 3:  a +=  (__u32)k[2] << 16; fallthrough;
    71  	case 2:  a +=  (__u32)k[1] <<  8; fallthrough;
    72  	case 1:  a +=  (__u32)k[0];
    73  
    74  		__jhash_final(a, b, c);
    75  		break;
    76  	case 0: /* Nothing left to add */
    77  		break;
    78  	}
    79  
    80  	return c;
    81  }
    82  
    83  static __always_inline __u32 __jhash_nwords(__u32 a, __u32 b, __u32 c,
    84  					    __u32 initval)
    85  {
    86  	a += initval;
    87  	b += initval;
    88  	c += initval;
    89  	__jhash_final(a, b, c);
    90  	return c;
    91  }
    92  
    93  static __always_inline __u32 jhash_3words(__u32 a, __u32 b, __u32 c,
    94  					  __u32 initval)
    95  {
    96  	return __jhash_nwords(a, b, c, initval + JHASH_INITVAL + (3 << 2));
    97  }
    98  
    99  static __always_inline __u32 jhash_2words(__u32 a, __u32 b, __u32 initval)
   100  {
   101  	return __jhash_nwords(a, b, 0, initval + JHASH_INITVAL + (2 << 2));
   102  }
   103  
   104  static __always_inline __u32 jhash_1word(__u32 a, __u32 initval)
   105  {
   106  	return __jhash_nwords(a, 0, 0, initval + JHASH_INITVAL + (1 << 2));
   107  }