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 }