]> git.proxmox.com Git - ceph.git/blame - ceph/src/seastar/dpdk/drivers/net/sfc/base/efx_hash.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / seastar / dpdk / drivers / net / sfc / base / efx_hash.c
CommitLineData
9f95a23c
TL
1/* SPDX-License-Identifier: BSD-3-Clause
2 *
11fdf7f2
TL
3 * Copyright 2006 Bob Jenkins
4 *
5 * Derived from public domain source, see
6 * <http://burtleburtle.net/bob/c/lookup3.c>:
7 *
8 * "lookup3.c, by Bob Jenkins, May 2006, Public Domain.
9 *
10 * These are functions for producing 32-bit hashes for hash table lookup...
11 * ...You can use this free for any purpose. It's in the public domain.
12 * It has no warranty."
13 *
9f95a23c 14 * Copyright (c) 2014-2018 Solarflare Communications Inc.
11fdf7f2 15 * All rights reserved.
11fdf7f2
TL
16 */
17
18#include "efx.h"
19#include "efx_impl.h"
20
21/* Hash initial value */
22#define EFX_HASH_INITIAL_VALUE 0xdeadbeef
23
24/*
25 * Rotate a 32-bit value left
26 *
27 * Allow platform to provide an intrinsic or optimised routine and
28 * fall-back to a simple shift based implementation.
29 */
30#if EFSYS_HAS_ROTL_DWORD
31
32#define EFX_HASH_ROTATE(_value, _shift) \
33 EFSYS_ROTL_DWORD(_value, _shift)
34
35#else
36
37#define EFX_HASH_ROTATE(_value, _shift) \
38 (((_value) << (_shift)) | ((_value) >> (32 - (_shift))))
39
40#endif
41
42/* Mix three 32-bit values reversibly */
43#define EFX_HASH_MIX(_a, _b, _c) \
44 do { \
45 _a -= _c; \
46 _a ^= EFX_HASH_ROTATE(_c, 4); \
47 _c += _b; \
48 _b -= _a; \
49 _b ^= EFX_HASH_ROTATE(_a, 6); \
50 _a += _c; \
51 _c -= _b; \
52 _c ^= EFX_HASH_ROTATE(_b, 8); \
53 _b += _a; \
54 _a -= _c; \
55 _a ^= EFX_HASH_ROTATE(_c, 16); \
56 _c += _b; \
57 _b -= _a; \
58 _b ^= EFX_HASH_ROTATE(_a, 19); \
59 _a += _c; \
60 _c -= _b; \
61 _c ^= EFX_HASH_ROTATE(_b, 4); \
62 _b += _a; \
63 _NOTE(CONSTANTCONDITION) \
64 } while (B_FALSE)
65
66/* Final mixing of three 32-bit values into one (_c) */
67#define EFX_HASH_FINALISE(_a, _b, _c) \
68 do { \
69 _c ^= _b; \
70 _c -= EFX_HASH_ROTATE(_b, 14); \
71 _a ^= _c; \
72 _a -= EFX_HASH_ROTATE(_c, 11); \
73 _b ^= _a; \
74 _b -= EFX_HASH_ROTATE(_a, 25); \
75 _c ^= _b; \
76 _c -= EFX_HASH_ROTATE(_b, 16); \
77 _a ^= _c; \
78 _a -= EFX_HASH_ROTATE(_c, 4); \
79 _b ^= _a; \
80 _b -= EFX_HASH_ROTATE(_a, 14); \
81 _c ^= _b; \
82 _c -= EFX_HASH_ROTATE(_b, 24); \
83 _NOTE(CONSTANTCONDITION) \
84 } while (B_FALSE)
85
86
87/* Produce a 32-bit hash from 32-bit aligned input */
88 __checkReturn uint32_t
89efx_hash_dwords(
90 __in_ecount(count) uint32_t const *input,
91 __in size_t count,
92 __in uint32_t init)
93{
94 uint32_t a;
95 uint32_t b;
96 uint32_t c;
97
98 /* Set up the initial internal state */
99 a = b = c = EFX_HASH_INITIAL_VALUE +
100 (((uint32_t)count) * sizeof (uint32_t)) + init;
101
102 /* Handle all but the last three dwords of the input */
103 while (count > 3) {
104 a += input[0];
105 b += input[1];
106 c += input[2];
107 EFX_HASH_MIX(a, b, c);
108
109 count -= 3;
110 input += 3;
111 }
112
113 /* Handle the left-overs */
114 switch (count) {
115 case 3:
116 c += input[2];
117 /* Fall-through */
118 case 2:
119 b += input[1];
120 /* Fall-through */
121 case 1:
122 a += input[0];
123 EFX_HASH_FINALISE(a, b, c);
124 break;
125
126 case 0:
127 /* Should only get here if count parameter was zero */
128 break;
129 }
130
131 return (c);
132}
133
134#if EFSYS_IS_BIG_ENDIAN
135
136/* Produce a 32-bit hash from arbitrarily aligned input */
137 __checkReturn uint32_t
138efx_hash_bytes(
139 __in_ecount(length) uint8_t const *input,
140 __in size_t length,
141 __in uint32_t init)
142{
143 uint32_t a;
144 uint32_t b;
145 uint32_t c;
146
147 /* Set up the initial internal state */
148 a = b = c = EFX_HASH_INITIAL_VALUE + (uint32_t)length + init;
149
150 /* Handle all but the last twelve bytes of the input */
151 while (length > 12) {
152 a += ((uint32_t)input[0]) << 24;
153 a += ((uint32_t)input[1]) << 16;
154 a += ((uint32_t)input[2]) << 8;
155 a += ((uint32_t)input[3]);
156 b += ((uint32_t)input[4]) << 24;
157 b += ((uint32_t)input[5]) << 16;
158 b += ((uint32_t)input[6]) << 8;
159 b += ((uint32_t)input[7]);
160 c += ((uint32_t)input[8]) << 24;
161 c += ((uint32_t)input[9]) << 16;
162 c += ((uint32_t)input[10]) << 8;
163 c += ((uint32_t)input[11]);
164 EFX_HASH_MIX(a, b, c);
165 length -= 12;
166 input += 12;
167 }
168
169 /* Handle the left-overs */
170 switch (length) {
171 case 12:
172 c += ((uint32_t)input[11]);
173 /* Fall-through */
174 case 11:
175 c += ((uint32_t)input[10]) << 8;
176 /* Fall-through */
177 case 10:
178 c += ((uint32_t)input[9]) << 16;
179 /* Fall-through */
180 case 9:
181 c += ((uint32_t)input[8]) << 24;
182 /* Fall-through */
183 case 8:
184 b += ((uint32_t)input[7]);
185 /* Fall-through */
186 case 7:
187 b += ((uint32_t)input[6]) << 8;
188 /* Fall-through */
189 case 6:
190 b += ((uint32_t)input[5]) << 16;
191 /* Fall-through */
192 case 5:
193 b += ((uint32_t)input[4]) << 24;
194 /* Fall-through */
195 case 4:
196 a += ((uint32_t)input[3]);
197 /* Fall-through */
198 case 3:
199 a += ((uint32_t)input[2]) << 8;
200 /* Fall-through */
201 case 2:
202 a += ((uint32_t)input[1]) << 16;
203 /* Fall-through */
204 case 1:
205 a += ((uint32_t)input[0]) << 24;
206 EFX_HASH_FINALISE(a, b, c);
207 break;
208
209 case 0:
210 /* Should only get here if length parameter was zero */
211 break;
212 }
213
214 return (c);
215}
216
217#elif EFSYS_IS_LITTLE_ENDIAN
218
219/* Produce a 32-bit hash from arbitrarily aligned input */
220 __checkReturn uint32_t
221efx_hash_bytes(
222 __in_ecount(length) uint8_t const *input,
223 __in size_t length,
224 __in uint32_t init)
225{
226 uint32_t a;
227 uint32_t b;
228 uint32_t c;
229
230 /* Set up the initial internal state */
231 a = b = c = EFX_HASH_INITIAL_VALUE + (uint32_t)length + init;
232
233 /* Handle all but the last twelve bytes of the input */
234 while (length > 12) {
235 a += ((uint32_t)input[0]);
236 a += ((uint32_t)input[1]) << 8;
237 a += ((uint32_t)input[2]) << 16;
238 a += ((uint32_t)input[3]) << 24;
239 b += ((uint32_t)input[4]);
240 b += ((uint32_t)input[5]) << 8;
241 b += ((uint32_t)input[6]) << 16;
242 b += ((uint32_t)input[7]) << 24;
243 c += ((uint32_t)input[8]);
244 c += ((uint32_t)input[9]) << 8;
245 c += ((uint32_t)input[10]) << 16;
246 c += ((uint32_t)input[11]) << 24;
247 EFX_HASH_MIX(a, b, c);
248 length -= 12;
249 input += 12;
250 }
251
252 /* Handle the left-overs */
253 switch (length) {
254 case 12:
255 c += ((uint32_t)input[11]) << 24;
256 /* Fall-through */
257 case 11:
258 c += ((uint32_t)input[10]) << 16;
259 /* Fall-through */
260 case 10:
261 c += ((uint32_t)input[9]) << 8;
262 /* Fall-through */
263 case 9:
264 c += ((uint32_t)input[8]);
265 /* Fall-through */
266 case 8:
267 b += ((uint32_t)input[7]) << 24;
268 /* Fall-through */
269 case 7:
270 b += ((uint32_t)input[6]) << 16;
271 /* Fall-through */
272 case 6:
273 b += ((uint32_t)input[5]) << 8;
274 /* Fall-through */
275 case 5:
276 b += ((uint32_t)input[4]);
277 /* Fall-through */
278 case 4:
279 a += ((uint32_t)input[3]) << 24;
280 /* Fall-through */
281 case 3:
282 a += ((uint32_t)input[2]) << 16;
283 /* Fall-through */
284 case 2:
285 a += ((uint32_t)input[1]) << 8;
286 /* Fall-through */
287 case 1:
288 a += ((uint32_t)input[0]);
289 EFX_HASH_FINALISE(a, b, c);
290 break;
291
292 case 0:
293 /* Should only get here if length parameter was zero */
294 break;
295 }
296
297 return (c);
298}
299
300#else
301
302#error "Neither of EFSYS_IS_{BIG,LITTLE}_ENDIAN is set"
303
304#endif