blob: fbe4275f9faeedbb5641eb3fbb67755c11e72c9d [file] [log] [blame]
Damjan Marion2e5921b2021-11-28 22:57:15 +01001/* SPDX-License-Identifier: Apache-2.0
2 * Copyright(c) 2021 Cisco Systems, Inc.
3 */
4
5#include <vppinfra/format.h>
6#include <vppinfra/vector/test/test.h>
7#include <vppinfra/vector/toeplitz.h>
8
9/* secret key and test cases taken from:
10 * https://docs.microsoft.com/en-us/windows-hardware/drivers/network/verifying-the-rss-hash-calculation
11 */
12
13typedef struct
14{
15 u32 sip, dip;
16 u16 sport, dport;
17} __clib_packed ip4_key_t;
18
19typedef struct
20{
21 ip4_key_t key;
22 u32 hash_2t, hash_4t;
23} ip4_test_t;
24
25typedef struct
26{
27 u16 sip[8], dip[8];
28 u16 sport, dport;
29} __clib_packed ip6_key_t;
30
31typedef struct
32{
33 ip6_key_t key;
34 u32 hash_2t, hash_4t;
35} ip6_test_t;
36
37#define N_IP4_TESTS 5
38#define N_IP6_TESTS 3
39#define N_LENGTH_TESTS 240
40
41#ifndef CLIB_MARCH_VARIANT
42#define _IP4(a, b, c, d) ((d) << 24 | (c) << 16 | (b) << 8 | (a))
43#define _IP6(a, b, c, d, e, f, g, h) \
44 { \
45 (u16) ((a) << 8) | (u8) ((a) >> 8), (u16) ((b) << 8) | (u8) ((b) >> 8), \
46 (u16) ((c) << 8) | (u8) ((c) >> 8), (u16) ((d) << 8) | (u8) ((d) >> 8), \
47 (u16) ((e) << 8) | (u8) ((e) >> 8), (u16) ((f) << 8) | (u8) ((f) >> 8), \
48 (u16) ((g) << 8) | (u8) ((g) >> 8), (u16) ((h) << 8) | (u8) ((h) >> 8), \
49 }
50#define _PORT(a) ((a) >> 8 | (((a) &0xff) << 8))
51
52const ip4_test_t ip4_tests[N_IP4_TESTS] = {
53 /* ipv4 tests */
54 {
55 .key.sip = _IP4 (66, 9, 149, 187),
56 .key.dip = _IP4 (161, 142, 100, 80),
57 .key.sport = _PORT (2794),
58 .key.dport = _PORT (1766),
59 .hash_2t = 0x323e8fc2,
60 .hash_4t = 0x51ccc178,
61 },
62 {
63 .key.sip = _IP4 (199, 92, 111, 2),
64 .key.dip = _IP4 (65, 69, 140, 83),
65 .key.sport = _PORT (14230),
66 .key.dport = _PORT (4739),
67 .hash_2t = 0xd718262a,
68 .hash_4t = 0xc626b0ea,
69 },
70 {
71 .key.sip = _IP4 (24, 19, 198, 95),
72 .key.dip = _IP4 (12, 22, 207, 184),
73 .key.sport = _PORT (12898),
74 .key.dport = _PORT (38024),
75 .hash_2t = 0xd2d0a5de,
76 .hash_4t = 0x5c2b394a,
77 },
78 {
79 .key.sip = _IP4 (38, 27, 205, 30),
80 .key.dip = _IP4 (209, 142, 163, 6),
81 .key.sport = _PORT (48228),
82 .key.dport = _PORT (2217),
83 .hash_2t = 0x82989176,
84 .hash_4t = 0xafc7327f,
85 },
86 {
87 .key.sip = _IP4 (153, 39, 163, 191),
88 .key.dip = _IP4 (202, 188, 127, 2),
89 .key.sport = _PORT (44251),
90 .key.dport = _PORT (1303),
91 .hash_2t = 0x5d1809c5,
92 .hash_4t = 0x10e828a2,
93 }
94};
95
96const ip6_test_t ip6_tests[N_IP6_TESTS] = {
97 {
98 .key.sip = _IP6 (0x3ffe, 0x2501, 0x200, 0x1fff, 0, 0, 0, 7),
99 .key.dip = _IP6 (0x3ffe, 0x2501, 0x200, 3, 0, 0, 0, 1),
100 .key.sport = _PORT (2794),
101 .key.dport = _PORT (1766),
102 .hash_2t = 0x2cc18cd5,
103 .hash_4t = 0x40207d3d,
104 },
105 {
106 .key.sip = _IP6 (0x3ffe, 0x501, 8, 0, 0x260, 0x97ff, 0xfe40, 0xefab),
107 .key.dip = _IP6 (0xff02, 0, 0, 0, 0, 0, 0, 1),
108 .key.sport = _PORT (14230),
109 .key.dport = _PORT (4739),
110 .hash_2t = 0x0f0c461c,
111 .hash_4t = 0xdde51bbf,
112 },
113 {
114 .key.sip = _IP6 (0x3ffe, 0x1900, 0x4545, 3, 0x200, 0xf8ff, 0xfe21, 0x67cf),
115 .key.dip = _IP6 (0xfe80, 0, 0, 0, 0x200, 0xf8ff, 0xfe21, 0x67cf),
116 .key.sport = _PORT (44251),
117 .key.dport = _PORT (38024),
118 .hash_2t = 0x4b61e985,
119 .hash_4t = 0x02d1feef,
120 }
121};
122
123const u32 length_test_hashes[N_LENGTH_TESTS] = {
124 0x00000000, 0x00000000, 0x2b6d12ad, 0x9de4446e, 0x061f00bf, 0xad7ed8f7,
125 0x4bc7b068, 0x231fc545, 0xdbd97a33, 0xcdab29e7, 0x2d665c0c, 0x31e28ed7,
126 0x14e19218, 0x5aa89f0f, 0xd47de07f, 0x355ec712, 0x7e1cbfc0, 0xf84de19d,
127 0xbcf66bd3, 0x104086c6, 0x71900b34, 0xcd2f9819, 0xeae68ebb, 0x54d63b4c,
128 0x5f865a2c, 0x9d6ded08, 0xe00b0912, 0x3fcf07a6, 0x3bd9ca93, 0x3f4f3bbb,
129 0xd0b82624, 0xa28a08e1, 0xa585969f, 0x0c8f4a71, 0x5dce7bdd, 0x4fcf2a6d,
130 0x91c89ae9, 0xbef8a24d, 0x8e3d30fe, 0xc8027848, 0xc1e7e513, 0xa12bd3d9,
131 0x46700bb4, 0xc6339dab, 0x970805ad, 0xfcb50ac8, 0xc6db4f44, 0x792e2987,
132 0xacfb7836, 0xa25ec529, 0x957d7beb, 0x6732809a, 0x891836ed, 0xeefb83b2,
133 0xca96b40b, 0x93fd5abd, 0x9076f922, 0x59adb4eb, 0x9705aafb, 0x282719b1,
134 0xdda9cb8a, 0x3f499131, 0x47491130, 0x30ef0759, 0xad1cf855, 0x428aa312,
135 0x4200240a, 0x71a72857, 0x16b30c36, 0x10cca9a3, 0x166f091e, 0x30e00560,
136 0x8acd20ba, 0xfa633d76, 0x0fe32eb7, 0xdcc0122f, 0x20aa8ab0, 0x62b2a9af,
137 0x7a6c80a6, 0x27e87268, 0x95b797a8, 0x25d18ccd, 0x68a7fb00, 0xc54bcdad,
138 0x3bd0e717, 0xf0df54c9, 0x780daadf, 0x7b435605, 0x150c1e10, 0x8a892e54,
139 0x9d27cb25, 0xe23383a5, 0x57aac408, 0x83b8abf8, 0x560f33af, 0xd5cb3307,
140 0x79ae8edc, 0x9b127665, 0x320f18bd, 0x385d636b, 0xbd1b2dbf, 0x97679888,
141 0x738894a4, 0xeba2afb0, 0xfa7c2d50, 0xb6741aa1, 0x28922bba, 0x7783242b,
142 0xa694cca2, 0xa32781c0, 0x696cd670, 0xa714d72f, 0xea34d35a, 0xc5aed81e,
143 0x0438433a, 0xc1939ab2, 0xb51c123a, 0x121426b9, 0x1add93ba, 0x50c56b6a,
144 0x7e90902a, 0xae3abd85, 0x2f7a0088, 0xb45cf6f9, 0x80070094, 0x8bd46467,
145 0xdfd1b762, 0x0bb25856, 0x48eefe84, 0x0989dbb9, 0xfc32472b, 0x965fec6b,
146 0x5a256bd0, 0x6df7127a, 0x7856d0d6, 0xedc82bd3, 0x1b563b96, 0xc73eace7,
147 0xba4c0a93, 0xdfd6dd97, 0x923c41db, 0x14926ca6, 0x22e52ab1, 0x22852a66,
148 0x79606b9c, 0xb0f22b23, 0xb46354ba, 0x9c3cd931, 0x03a92bd6, 0x84000834,
149 0x5425df65, 0xf4dd3fc9, 0x391cc873, 0xa560b52e, 0x828037d9, 0x31323dd5,
150 0x5c6e3147, 0x28e21f85, 0xa431eb51, 0xf468c4a3, 0x9bea1d2e, 0x43d9109c,
151 0x5bb9b081, 0xe0825675, 0xc9c92591, 0xd29fc812, 0x03136bc9, 0x5e005a1f,
152 0x6d821ed8, 0x3f0bfcc4, 0x24774162, 0x893bde94, 0x6475efea, 0x6711538e,
153 0xc4755f6d, 0x9425ebe2, 0xacf471b4, 0xb947ab0c, 0x1f78c455, 0x372b3ed7,
154 0xb3ec24d7, 0x18c4459f, 0xa8ff3695, 0xe4aa2b85, 0x8a52ad7e, 0xe05e8177,
155 0x7aa348ed, 0x3e4ac6aa, 0x17dcf8a5, 0x93b933b0, 0x8f7413ec, 0xc77bfe61,
156 0xfdb72874, 0x4370f138, 0xdf3462ad, 0xc8970a59, 0xb4a9fed8, 0xa2ddc39b,
157 0xd61db62a, 0x95c5fc1b, 0x7b22e6e0, 0x1969702c, 0x7992aebb, 0x59d7c225,
158 0x0e16db0b, 0x9f2afc21, 0x246cf66b, 0xb3d6569d, 0x29c532d7, 0xe155747a,
159 0xe38d7872, 0xea704969, 0xb69095b0, 0x1b198efd, 0x55daab76, 0xa2a377b6,
160 0xb31aa2fa, 0x48b73c41, 0xf0cc501a, 0x9c9ca831, 0x1b591b99, 0xb2d8d22f,
161 0xab4b5f69, 0x4fe00e71, 0xdf5480bd, 0x982540d7, 0x7f34ea4f, 0xd7be66e1,
162 0x9d2ab1ba, 0x1ba62e12, 0xee3fb36c, 0xf28d7c5a, 0x756311eb, 0xc68567f2,
163 0x7b6ea177, 0xc398d9f3
164};
165
166#else
167extern const ip4_test_t ip4_tests[N_IP4_TESTS];
168extern const ip6_test_t ip6_tests[N_IP6_TESTS];
169extern const u32 length_test_hashes[N_LENGTH_TESTS];
170#endif
171
172__test_funct_fn u32
173wrapper (clib_toeplitz_hash_key_t *k, u8 *data, u32 n_bytes)
174{
175 return clib_toeplitz_hash (k, data, n_bytes);
176}
177
Damjan Marion88019c42021-12-15 10:17:04 +0000178__test_funct_fn void
179wrapper_x4 (clib_toeplitz_hash_key_t *k, u8 *d0, u8 *d1, u8 *d2, u8 *d3,
180 u32 *h0, u32 *h1, u32 *h2, u32 *h3, u32 n_bytes)
181{
182 clib_toeplitz_hash_x4 (k, d0, d1, d2, d3, h0, h1, h2, h3, n_bytes);
183}
184
Damjan Marion2e5921b2021-11-28 22:57:15 +0100185static clib_error_t *
186test_clib_toeplitz_hash (clib_error_t *err)
187{
188 u32 r;
189 int n_key_copies, bigkey_len, bigdata_len;
190 u8 *bigkey, *bigdata;
191 clib_toeplitz_hash_key_t *k;
192
193 k = clib_toeplitz_hash_key_init (0, 0);
194
195 for (int i = 0; i < N_IP4_TESTS; i++)
196 {
197 r = wrapper (k, (u8 *) &ip4_tests[i].key, 8);
198 if (ip4_tests[i].hash_2t != r)
199 return clib_error_return (err,
200 "wrong IPv4 2 tuple hash for test %u, "
201 "calculated 0x%08x expected 0x%08x",
202 i, ip4_tests[i].hash_2t, r);
203
204 r = wrapper (k, (u8 *) &ip4_tests[i].key, 12);
205 if (ip4_tests[i].hash_4t != r)
206 return clib_error_return (err,
207 "wrong IPv4 4 tuple hash for test %u, "
208 "calculated 0x%08x expected 0x%08x",
209 i, ip4_tests[i].hash_4t, r);
210 }
211
212 for (int i = 0; i < N_IP6_TESTS; i++)
213 {
214 r = wrapper (k, (u8 *) &ip6_tests[i].key, 32);
215 if (ip6_tests[i].hash_2t != r)
216 return clib_error_return (err,
217 "wrong IPv6 2 tuple hash for test %u, "
218 "calculated 0x%08x expected 0x%08x",
219 i, ip6_tests[i].hash_2t, r);
220
221 r = wrapper (k, (u8 *) &ip6_tests[i].key, 36);
222 if (ip6_tests[i].hash_4t != r)
223 return clib_error_return (err,
224 "wrong IPv6 4 tuple hash for test %u, "
225 "calculated 0x%08x expected 0x%08x",
226 i, ip6_tests[i].hash_4t, r);
227 }
228
229 n_key_copies = 6;
230 bigkey_len = k->key_length * n_key_copies;
231 bigdata_len = bigkey_len - 4;
Damjan Marion88019c42021-12-15 10:17:04 +0000232 bigkey = test_mem_alloc_and_splat (k->key_length, n_key_copies, k->data);
233 bigdata = test_mem_alloc_and_fill_inc_u8 (bigdata_len, 0, 0);
Damjan Marion2e5921b2021-11-28 22:57:15 +0100234 u32 key_len = k->key_length;
235
Damjan Marion2e5921b2021-11-28 22:57:15 +0100236 clib_toeplitz_hash_key_free (k);
237 k = clib_toeplitz_hash_key_init (bigkey, n_key_copies * key_len);
238
239 for (int i = 0; i < N_LENGTH_TESTS - 4; i++)
240 {
241 r = wrapper (k, bigdata, i);
242 if (length_test_hashes[i] != r)
243 {
244 err = clib_error_return (err,
245 "wrong length test hash for length %u, "
246 "calculated 0x%08x expected 0x%08x "
247 "xor 0x%08x",
248 i, r, length_test_hashes[i],
249 r ^ length_test_hashes[i]);
250 goto done;
251 }
252 }
253
254done:
255 clib_toeplitz_hash_key_free (k);
Damjan Marion88019c42021-12-15 10:17:04 +0000256 test_mem_free (bigkey);
257 test_mem_free (bigdata);
Damjan Marion2e5921b2021-11-28 22:57:15 +0100258 return err;
259}
260
261void __test_perf_fn
Damjan Mariond5045e62022-04-06 21:16:37 +0200262perftest_fixed_12byte (test_perf_t *tp)
Damjan Marion2e5921b2021-11-28 22:57:15 +0100263{
264 u32 n = tp->n_ops;
265 u8 *data = test_mem_alloc_and_splat (12, n, (void *) &ip4_tests[0].key);
266 u8 *res = test_mem_alloc (4 * n);
267 clib_toeplitz_hash_key_t *k = clib_toeplitz_hash_key_init (0, 0);
268
Damjan Mariond5045e62022-04-06 21:16:37 +0200269 test_perf_event_enable (tp);
Damjan Marion2e5921b2021-11-28 22:57:15 +0100270 for (int i = 0; i < n; i++)
271 ((u32 *) res)[i] = clib_toeplitz_hash (k, data + i * 12, 12);
Damjan Mariond5045e62022-04-06 21:16:37 +0200272 test_perf_event_disable (tp);
Damjan Marion2e5921b2021-11-28 22:57:15 +0100273
274 clib_toeplitz_hash_key_free (k);
275 test_mem_free (data);
276 test_mem_free (res);
277}
278
279void __test_perf_fn
Damjan Mariond5045e62022-04-06 21:16:37 +0200280perftest_fixed_36byte (test_perf_t *tp)
Damjan Marion2e5921b2021-11-28 22:57:15 +0100281{
282 u32 n = tp->n_ops;
283 u8 *data = test_mem_alloc_and_splat (36, n, (void *) &ip6_tests[0].key);
284 u8 *res = test_mem_alloc (4 * n);
285 clib_toeplitz_hash_key_t *k = clib_toeplitz_hash_key_init (0, 0);
286
Damjan Mariond5045e62022-04-06 21:16:37 +0200287 test_perf_event_enable (tp);
Damjan Marion2e5921b2021-11-28 22:57:15 +0100288 for (int i = 0; i < n; i++)
289 ((u32 *) res)[i] = clib_toeplitz_hash (k, data + i * 36, 36);
Damjan Mariond5045e62022-04-06 21:16:37 +0200290 test_perf_event_disable (tp);
Damjan Marion2e5921b2021-11-28 22:57:15 +0100291
292 clib_toeplitz_hash_key_free (k);
293 test_mem_free (data);
294 test_mem_free (res);
295}
296
297void __test_perf_fn
Damjan Mariond5045e62022-04-06 21:16:37 +0200298perftest_variable_size (test_perf_t *tp)
Damjan Marion2e5921b2021-11-28 22:57:15 +0100299{
300 u32 key_len, n_keys, n = tp->n_ops;
301 u8 *key, *data = test_mem_alloc (n);
302 u32 *res = test_mem_alloc (sizeof (u32));
303 clib_toeplitz_hash_key_t *k = clib_toeplitz_hash_key_init (0, 0);
304
305 k = clib_toeplitz_hash_key_init (0, 0);
306 key_len = k->key_length;
307 n_keys = ((n + 4) / k->key_length) + 1;
308 key = test_mem_alloc_and_splat (n_keys, key_len, k->data);
309 clib_toeplitz_hash_key_free (k);
310 k = clib_toeplitz_hash_key_init (key, key_len * n_keys);
311
Damjan Mariond5045e62022-04-06 21:16:37 +0200312 test_perf_event_enable (tp);
Damjan Marion2e5921b2021-11-28 22:57:15 +0100313 res[0] = clib_toeplitz_hash (k, data, n);
Damjan Mariond5045e62022-04-06 21:16:37 +0200314 test_perf_event_disable (tp);
Damjan Marion2e5921b2021-11-28 22:57:15 +0100315
316 clib_toeplitz_hash_key_free (k);
317 test_mem_free (data);
318 test_mem_free (res);
319 test_mem_free (key);
320}
321
322REGISTER_TEST (clib_toeplitz_hash) = {
323 .name = "clib_toeplitz_hash",
324 .fn = test_clib_toeplitz_hash,
Damjan Mariond5045e62022-04-06 21:16:37 +0200325 .perf_tests = PERF_TESTS ({ .name = "fixed (per 12 byte tuple)",
Damjan Marion2e5921b2021-11-28 22:57:15 +0100326 .n_ops = 1024,
327 .fn = perftest_fixed_12byte },
Damjan Mariond5045e62022-04-06 21:16:37 +0200328 { .name = "fixed (per 36 byte tuple)",
Damjan Marion2e5921b2021-11-28 22:57:15 +0100329 .n_ops = 1024,
330 .fn = perftest_fixed_36byte },
Damjan Mariond5045e62022-04-06 21:16:37 +0200331 { .name = "variable size (per byte)",
Damjan Marion2e5921b2021-11-28 22:57:15 +0100332 .n_ops = 16384,
333 .fn = perftest_variable_size }),
334};
Damjan Marion88019c42021-12-15 10:17:04 +0000335
336static clib_error_t *
337test_clib_toeplitz_hash_x4 (clib_error_t *err)
338{
339 u32 r[4];
340 int n_key_copies, bigkey_len, bigdata_len;
341 u8 *bigkey, *bigdata0, *bigdata1, *bigdata2, *bigdata3;
342 clib_toeplitz_hash_key_t *k;
343
344 k = clib_toeplitz_hash_key_init (0, 0);
345
346 wrapper_x4 (k, (u8 *) &ip4_tests[0].key, (u8 *) &ip4_tests[1].key,
347 (u8 *) &ip4_tests[2].key, (u8 *) &ip4_tests[3].key, r, r + 1,
348 r + 2, r + 3, 8);
349
350 if (ip4_tests[0].hash_2t != r[0] || ip4_tests[1].hash_2t != r[1] ||
351 ip4_tests[2].hash_2t != r[2] || ip4_tests[3].hash_2t != r[3])
352 return clib_error_return (err,
353 "wrong IPv4 2 tuple x4 hash "
354 "calculated { 0x%08x, 0x%08x, 0x%08x, 0x%08x } "
355 "expected { 0x%08x, 0x%08x, 0x%08x, 0x%08x }",
356 ip4_tests[0].hash_2t, ip4_tests[1].hash_2t,
357 ip4_tests[2].hash_2t, ip4_tests[3].hash_2t, r[0],
358 r[1], r[2], r[3]);
359
360 wrapper_x4 (k, (u8 *) &ip4_tests[0].key, (u8 *) &ip4_tests[1].key,
361 (u8 *) &ip4_tests[2].key, (u8 *) &ip4_tests[3].key, r, r + 1,
362 r + 2, r + 3, 12);
363
364 if (ip4_tests[0].hash_4t != r[0] || ip4_tests[1].hash_4t != r[1] ||
365 ip4_tests[2].hash_4t != r[2] || ip4_tests[3].hash_4t != r[3])
366 return clib_error_return (err,
367 "wrong IPv4 4 tuple x4 hash "
368 "calculated { 0x%08x, 0x%08x, 0x%08x, 0x%08x } "
369 "expected { 0x%08x, 0x%08x, 0x%08x, 0x%08x }",
370 ip4_tests[0].hash_4t, ip4_tests[1].hash_4t,
371 ip4_tests[2].hash_4t, ip4_tests[3].hash_4t, r[0],
372 r[1], r[2], r[3]);
373
374 wrapper_x4 (k, (u8 *) &ip6_tests[0].key, (u8 *) &ip6_tests[1].key,
375 (u8 *) &ip6_tests[2].key, (u8 *) &ip6_tests[0].key, r, r + 1,
376 r + 2, r + 3, 32);
377
378 if (ip6_tests[0].hash_2t != r[0] || ip6_tests[1].hash_2t != r[1] ||
379 ip6_tests[2].hash_2t != r[2] || ip6_tests[0].hash_2t != r[3])
380 return clib_error_return (err,
381 "wrong IPv6 2 tuple x4 hash "
382 "calculated { 0x%08x, 0x%08x, 0x%08x, 0x%08x } "
383 "expected { 0x%08x, 0x%08x, 0x%08x, 0x%08x }",
384 ip6_tests[0].hash_2t, ip6_tests[1].hash_2t,
385 ip6_tests[2].hash_2t, ip6_tests[0].hash_2t, r[0],
386 r[1], r[2], r[3]);
387
388 wrapper_x4 (k, (u8 *) &ip6_tests[0].key, (u8 *) &ip6_tests[1].key,
389 (u8 *) &ip6_tests[2].key, (u8 *) &ip6_tests[0].key, r, r + 1,
390 r + 2, r + 3, 36);
391
392 if (ip6_tests[0].hash_4t != r[0] || ip6_tests[1].hash_4t != r[1] ||
393 ip6_tests[2].hash_4t != r[2] || ip6_tests[0].hash_4t != r[3])
394 return clib_error_return (err,
395 "wrong IPv6 4 tuple x4 hash "
396 "calculated { 0x%08x, 0x%08x, 0x%08x, 0x%08x } "
397 "expected { 0x%08x, 0x%08x, 0x%08x, 0x%08x }",
398 ip6_tests[0].hash_4t, ip6_tests[1].hash_4t,
399 ip6_tests[2].hash_4t, ip6_tests[0].hash_4t, r[0],
400 r[1], r[2], r[3]);
401
402 n_key_copies = 6;
403 bigkey_len = k->key_length * n_key_copies;
404 bigdata_len = bigkey_len - 4;
405 bigkey = test_mem_alloc_and_splat (k->key_length, n_key_copies, k->data);
406 bigdata0 = test_mem_alloc_and_fill_inc_u8 (bigdata_len, 0, 0);
407 bigdata1 = test_mem_alloc_and_fill_inc_u8 (bigdata_len, 0, 0);
408 bigdata2 = test_mem_alloc_and_fill_inc_u8 (bigdata_len, 0, 0);
409 bigdata3 = test_mem_alloc_and_fill_inc_u8 (bigdata_len, 0, 0);
410 u32 key_len = k->key_length;
411
412 clib_toeplitz_hash_key_free (k);
413 k = clib_toeplitz_hash_key_init (bigkey, n_key_copies * key_len);
414
415 for (int i = 0; i < N_LENGTH_TESTS - 4; i++)
416 {
417 wrapper_x4 (k, bigdata0, bigdata1, bigdata2, bigdata3, r, r + 1, r + 2,
418 r + 3, i);
419 if (length_test_hashes[i] != r[0] || length_test_hashes[i] != r[1] ||
420 length_test_hashes[i] != r[2] || length_test_hashes[i] != r[3])
421 {
422 err = clib_error_return (
423 err,
424 "wrong length test hash x4 for length %u, "
425 "calculated { 0x%08x, 0x%08x, 0x%08x, 0x%08x }, expected 0x%08x",
426 i, r[0], r[1], r[2], r[3], length_test_hashes[i]);
427 goto done;
428 }
429 }
430
431done:
432 clib_toeplitz_hash_key_free (k);
433 test_mem_free (bigkey);
434 test_mem_free (bigdata0);
435 test_mem_free (bigdata1);
436 test_mem_free (bigdata2);
437 test_mem_free (bigdata3);
438 return err;
439}
440
441void __test_perf_fn
Damjan Mariond5045e62022-04-06 21:16:37 +0200442perftest_fixed_12byte_x4 (test_perf_t *tp)
Damjan Marion88019c42021-12-15 10:17:04 +0000443{
444 u32 n = tp->n_ops / 4;
445 u8 *d0 = test_mem_alloc_and_splat (12, n, (void *) &ip4_tests[0].key);
446 u8 *d1 = test_mem_alloc_and_splat (12, n, (void *) &ip4_tests[1].key);
447 u8 *d2 = test_mem_alloc_and_splat (12, n, (void *) &ip4_tests[2].key);
448 u8 *d3 = test_mem_alloc_and_splat (12, n, (void *) &ip4_tests[3].key);
449 u32 *h0 = test_mem_alloc (4 * n);
450 u32 *h1 = test_mem_alloc (4 * n);
451 u32 *h2 = test_mem_alloc (4 * n);
452 u32 *h3 = test_mem_alloc (4 * n);
453 clib_toeplitz_hash_key_t *k = clib_toeplitz_hash_key_init (0, 0);
454
Damjan Mariond5045e62022-04-06 21:16:37 +0200455 test_perf_event_enable (tp);
Damjan Marion88019c42021-12-15 10:17:04 +0000456 for (int i = 0; i < n; i++)
457 clib_toeplitz_hash_x4 (k, d0 + i * 12, d1 + i * 12, d2 + i * 12,
458 d3 + i * 12, h0 + i, h1 + i, h2 + i, h3 + i, 12);
Damjan Mariond5045e62022-04-06 21:16:37 +0200459 test_perf_event_disable (tp);
Damjan Marion88019c42021-12-15 10:17:04 +0000460
461 clib_toeplitz_hash_key_free (k);
462 test_mem_free (d0);
463 test_mem_free (d1);
464 test_mem_free (d2);
465 test_mem_free (d3);
466 test_mem_free (h0);
467 test_mem_free (h1);
468 test_mem_free (h2);
469 test_mem_free (h3);
470}
471
472void __test_perf_fn
Damjan Mariond5045e62022-04-06 21:16:37 +0200473perftest_fixed_36byte_x4 (test_perf_t *tp)
Damjan Marion88019c42021-12-15 10:17:04 +0000474{
475 u32 n = tp->n_ops / 4;
476 u8 *d0 = test_mem_alloc_and_splat (36, n, (void *) &ip4_tests[0].key);
477 u8 *d1 = test_mem_alloc_and_splat (36, n, (void *) &ip4_tests[1].key);
478 u8 *d2 = test_mem_alloc_and_splat (36, n, (void *) &ip4_tests[2].key);
479 u8 *d3 = test_mem_alloc_and_splat (36, n, (void *) &ip4_tests[3].key);
480 u32 *h0 = test_mem_alloc (4 * n);
481 u32 *h1 = test_mem_alloc (4 * n);
482 u32 *h2 = test_mem_alloc (4 * n);
483 u32 *h3 = test_mem_alloc (4 * n);
484 clib_toeplitz_hash_key_t *k = clib_toeplitz_hash_key_init (0, 0);
485
Damjan Mariond5045e62022-04-06 21:16:37 +0200486 test_perf_event_enable (tp);
Damjan Marion88019c42021-12-15 10:17:04 +0000487 for (int i = 0; i < n; i++)
488 clib_toeplitz_hash_x4 (k, d0 + i * 36, d1 + i * 36, d2 + i * 36,
489 d3 + i * 36, h0 + i, h1 + i, h2 + i, h3 + i, 36);
Damjan Mariond5045e62022-04-06 21:16:37 +0200490 test_perf_event_disable (tp);
Damjan Marion88019c42021-12-15 10:17:04 +0000491
492 clib_toeplitz_hash_key_free (k);
493 test_mem_free (d0);
494 test_mem_free (d1);
495 test_mem_free (d2);
496 test_mem_free (d3);
497 test_mem_free (h0);
498 test_mem_free (h1);
499 test_mem_free (h2);
500 test_mem_free (h3);
501}
502
503void __test_perf_fn
Damjan Mariond5045e62022-04-06 21:16:37 +0200504perftest_variable_size_x4 (test_perf_t *tp)
Damjan Marion88019c42021-12-15 10:17:04 +0000505{
506 u32 key_len, n_keys, n = tp->n_ops / 4;
507 u8 *key;
508 u8 *d0 = test_mem_alloc (n);
509 u8 *d1 = test_mem_alloc (n);
510 u8 *d2 = test_mem_alloc (n);
511 u8 *d3 = test_mem_alloc (n);
512 u32 *h0 = test_mem_alloc (sizeof (u32));
513 u32 *h1 = test_mem_alloc (sizeof (u32));
514 u32 *h2 = test_mem_alloc (sizeof (u32));
515 u32 *h3 = test_mem_alloc (sizeof (u32));
516 clib_toeplitz_hash_key_t *k = clib_toeplitz_hash_key_init (0, 0);
517
518 k = clib_toeplitz_hash_key_init (0, 0);
519 key_len = k->key_length;
520 n_keys = ((n + 4) / k->key_length) + 1;
521 key = test_mem_alloc_and_splat (n_keys, key_len, k->data);
522 clib_toeplitz_hash_key_free (k);
523 k = clib_toeplitz_hash_key_init (key, key_len * n_keys);
524
Damjan Mariond5045e62022-04-06 21:16:37 +0200525 test_perf_event_enable (tp);
Damjan Marion88019c42021-12-15 10:17:04 +0000526 clib_toeplitz_hash_x4 (k, d0, d1, d2, d3, h0, h1, h2, h3, n);
Damjan Mariond5045e62022-04-06 21:16:37 +0200527 test_perf_event_disable (tp);
Damjan Marion88019c42021-12-15 10:17:04 +0000528
529 clib_toeplitz_hash_key_free (k);
530 test_mem_free (key);
531 test_mem_free (d0);
532 test_mem_free (d1);
533 test_mem_free (d2);
534 test_mem_free (d3);
535 test_mem_free (h0);
536 test_mem_free (h1);
537 test_mem_free (h2);
538 test_mem_free (h3);
539}
540
541REGISTER_TEST (clib_toeplitz_hash_x4) = {
542 .name = "clib_toeplitz_hash_x4",
543 .fn = test_clib_toeplitz_hash_x4,
Damjan Mariond5045e62022-04-06 21:16:37 +0200544 .perf_tests = PERF_TESTS ({ .name = "fixed (per 12 byte tuple)",
Damjan Marion88019c42021-12-15 10:17:04 +0000545 .n_ops = 1024,
546 .fn = perftest_fixed_12byte_x4 },
Damjan Mariond5045e62022-04-06 21:16:37 +0200547 { .name = "fixed (per 36 byte tuple)",
Damjan Marion88019c42021-12-15 10:17:04 +0000548 .n_ops = 1024,
549 .fn = perftest_fixed_36byte_x4 },
Damjan Mariond5045e62022-04-06 21:16:37 +0200550 { .name = "variable size (per byte)",
Damjan Marion88019c42021-12-15 10:17:04 +0000551 .n_ops = 16384,
552 .fn = perftest_variable_size_x4 }),
553};