blob: 708fd0e60fc384c1222621b379c1a9f2124c052d [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>
Damjan Marionc3542e12023-03-15 11:42:06 +00006#include <vppinfra/test/test.h>
Damjan Marion2e5921b2021-11-28 22:57:15 +01007#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 Marion2e5921b2021-11-28 22:57:15 +0100256 return err;
257}
258
259void __test_perf_fn
Damjan Mariond5045e62022-04-06 21:16:37 +0200260perftest_fixed_12byte (test_perf_t *tp)
Damjan Marion2e5921b2021-11-28 22:57:15 +0100261{
262 u32 n = tp->n_ops;
263 u8 *data = test_mem_alloc_and_splat (12, n, (void *) &ip4_tests[0].key);
264 u8 *res = test_mem_alloc (4 * n);
265 clib_toeplitz_hash_key_t *k = clib_toeplitz_hash_key_init (0, 0);
266
Damjan Mariond5045e62022-04-06 21:16:37 +0200267 test_perf_event_enable (tp);
Damjan Marion2e5921b2021-11-28 22:57:15 +0100268 for (int i = 0; i < n; i++)
269 ((u32 *) res)[i] = clib_toeplitz_hash (k, data + i * 12, 12);
Damjan Mariond5045e62022-04-06 21:16:37 +0200270 test_perf_event_disable (tp);
Damjan Marion2e5921b2021-11-28 22:57:15 +0100271
272 clib_toeplitz_hash_key_free (k);
Damjan Marion2e5921b2021-11-28 22:57:15 +0100273}
274
275void __test_perf_fn
Damjan Mariond5045e62022-04-06 21:16:37 +0200276perftest_fixed_36byte (test_perf_t *tp)
Damjan Marion2e5921b2021-11-28 22:57:15 +0100277{
278 u32 n = tp->n_ops;
279 u8 *data = test_mem_alloc_and_splat (36, n, (void *) &ip6_tests[0].key);
280 u8 *res = test_mem_alloc (4 * n);
281 clib_toeplitz_hash_key_t *k = clib_toeplitz_hash_key_init (0, 0);
282
Damjan Mariond5045e62022-04-06 21:16:37 +0200283 test_perf_event_enable (tp);
Damjan Marion2e5921b2021-11-28 22:57:15 +0100284 for (int i = 0; i < n; i++)
285 ((u32 *) res)[i] = clib_toeplitz_hash (k, data + i * 36, 36);
Damjan Mariond5045e62022-04-06 21:16:37 +0200286 test_perf_event_disable (tp);
Damjan Marion2e5921b2021-11-28 22:57:15 +0100287
288 clib_toeplitz_hash_key_free (k);
Damjan Marion2e5921b2021-11-28 22:57:15 +0100289}
290
291void __test_perf_fn
Damjan Mariond5045e62022-04-06 21:16:37 +0200292perftest_variable_size (test_perf_t *tp)
Damjan Marion2e5921b2021-11-28 22:57:15 +0100293{
294 u32 key_len, n_keys, n = tp->n_ops;
295 u8 *key, *data = test_mem_alloc (n);
296 u32 *res = test_mem_alloc (sizeof (u32));
297 clib_toeplitz_hash_key_t *k = clib_toeplitz_hash_key_init (0, 0);
298
299 k = clib_toeplitz_hash_key_init (0, 0);
300 key_len = k->key_length;
301 n_keys = ((n + 4) / k->key_length) + 1;
302 key = test_mem_alloc_and_splat (n_keys, key_len, k->data);
303 clib_toeplitz_hash_key_free (k);
304 k = clib_toeplitz_hash_key_init (key, key_len * n_keys);
305
Damjan Mariond5045e62022-04-06 21:16:37 +0200306 test_perf_event_enable (tp);
Damjan Marion2e5921b2021-11-28 22:57:15 +0100307 res[0] = clib_toeplitz_hash (k, data, n);
Damjan Mariond5045e62022-04-06 21:16:37 +0200308 test_perf_event_disable (tp);
Damjan Marion2e5921b2021-11-28 22:57:15 +0100309
310 clib_toeplitz_hash_key_free (k);
Damjan Marion2e5921b2021-11-28 22:57:15 +0100311}
312
313REGISTER_TEST (clib_toeplitz_hash) = {
314 .name = "clib_toeplitz_hash",
315 .fn = test_clib_toeplitz_hash,
Damjan Mariond5045e62022-04-06 21:16:37 +0200316 .perf_tests = PERF_TESTS ({ .name = "fixed (per 12 byte tuple)",
Damjan Marion2e5921b2021-11-28 22:57:15 +0100317 .n_ops = 1024,
318 .fn = perftest_fixed_12byte },
Damjan Mariond5045e62022-04-06 21:16:37 +0200319 { .name = "fixed (per 36 byte tuple)",
Damjan Marion2e5921b2021-11-28 22:57:15 +0100320 .n_ops = 1024,
321 .fn = perftest_fixed_36byte },
Damjan Mariond5045e62022-04-06 21:16:37 +0200322 { .name = "variable size (per byte)",
Damjan Marion2e5921b2021-11-28 22:57:15 +0100323 .n_ops = 16384,
324 .fn = perftest_variable_size }),
325};
Damjan Marion88019c42021-12-15 10:17:04 +0000326
327static clib_error_t *
328test_clib_toeplitz_hash_x4 (clib_error_t *err)
329{
330 u32 r[4];
331 int n_key_copies, bigkey_len, bigdata_len;
332 u8 *bigkey, *bigdata0, *bigdata1, *bigdata2, *bigdata3;
333 clib_toeplitz_hash_key_t *k;
334
335 k = clib_toeplitz_hash_key_init (0, 0);
336
337 wrapper_x4 (k, (u8 *) &ip4_tests[0].key, (u8 *) &ip4_tests[1].key,
338 (u8 *) &ip4_tests[2].key, (u8 *) &ip4_tests[3].key, r, r + 1,
339 r + 2, r + 3, 8);
340
341 if (ip4_tests[0].hash_2t != r[0] || ip4_tests[1].hash_2t != r[1] ||
342 ip4_tests[2].hash_2t != r[2] || ip4_tests[3].hash_2t != r[3])
343 return clib_error_return (err,
344 "wrong IPv4 2 tuple x4 hash "
345 "calculated { 0x%08x, 0x%08x, 0x%08x, 0x%08x } "
346 "expected { 0x%08x, 0x%08x, 0x%08x, 0x%08x }",
347 ip4_tests[0].hash_2t, ip4_tests[1].hash_2t,
348 ip4_tests[2].hash_2t, ip4_tests[3].hash_2t, r[0],
349 r[1], r[2], r[3]);
350
351 wrapper_x4 (k, (u8 *) &ip4_tests[0].key, (u8 *) &ip4_tests[1].key,
352 (u8 *) &ip4_tests[2].key, (u8 *) &ip4_tests[3].key, r, r + 1,
353 r + 2, r + 3, 12);
354
355 if (ip4_tests[0].hash_4t != r[0] || ip4_tests[1].hash_4t != r[1] ||
356 ip4_tests[2].hash_4t != r[2] || ip4_tests[3].hash_4t != r[3])
357 return clib_error_return (err,
358 "wrong IPv4 4 tuple x4 hash "
359 "calculated { 0x%08x, 0x%08x, 0x%08x, 0x%08x } "
360 "expected { 0x%08x, 0x%08x, 0x%08x, 0x%08x }",
361 ip4_tests[0].hash_4t, ip4_tests[1].hash_4t,
362 ip4_tests[2].hash_4t, ip4_tests[3].hash_4t, r[0],
363 r[1], r[2], r[3]);
364
365 wrapper_x4 (k, (u8 *) &ip6_tests[0].key, (u8 *) &ip6_tests[1].key,
366 (u8 *) &ip6_tests[2].key, (u8 *) &ip6_tests[0].key, r, r + 1,
367 r + 2, r + 3, 32);
368
369 if (ip6_tests[0].hash_2t != r[0] || ip6_tests[1].hash_2t != r[1] ||
370 ip6_tests[2].hash_2t != r[2] || ip6_tests[0].hash_2t != r[3])
371 return clib_error_return (err,
372 "wrong IPv6 2 tuple x4 hash "
373 "calculated { 0x%08x, 0x%08x, 0x%08x, 0x%08x } "
374 "expected { 0x%08x, 0x%08x, 0x%08x, 0x%08x }",
375 ip6_tests[0].hash_2t, ip6_tests[1].hash_2t,
376 ip6_tests[2].hash_2t, ip6_tests[0].hash_2t, r[0],
377 r[1], r[2], r[3]);
378
379 wrapper_x4 (k, (u8 *) &ip6_tests[0].key, (u8 *) &ip6_tests[1].key,
380 (u8 *) &ip6_tests[2].key, (u8 *) &ip6_tests[0].key, r, r + 1,
381 r + 2, r + 3, 36);
382
383 if (ip6_tests[0].hash_4t != r[0] || ip6_tests[1].hash_4t != r[1] ||
384 ip6_tests[2].hash_4t != r[2] || ip6_tests[0].hash_4t != r[3])
385 return clib_error_return (err,
386 "wrong IPv6 4 tuple x4 hash "
387 "calculated { 0x%08x, 0x%08x, 0x%08x, 0x%08x } "
388 "expected { 0x%08x, 0x%08x, 0x%08x, 0x%08x }",
389 ip6_tests[0].hash_4t, ip6_tests[1].hash_4t,
390 ip6_tests[2].hash_4t, ip6_tests[0].hash_4t, r[0],
391 r[1], r[2], r[3]);
392
393 n_key_copies = 6;
394 bigkey_len = k->key_length * n_key_copies;
395 bigdata_len = bigkey_len - 4;
396 bigkey = test_mem_alloc_and_splat (k->key_length, n_key_copies, k->data);
397 bigdata0 = test_mem_alloc_and_fill_inc_u8 (bigdata_len, 0, 0);
398 bigdata1 = test_mem_alloc_and_fill_inc_u8 (bigdata_len, 0, 0);
399 bigdata2 = test_mem_alloc_and_fill_inc_u8 (bigdata_len, 0, 0);
400 bigdata3 = test_mem_alloc_and_fill_inc_u8 (bigdata_len, 0, 0);
401 u32 key_len = k->key_length;
402
403 clib_toeplitz_hash_key_free (k);
404 k = clib_toeplitz_hash_key_init (bigkey, n_key_copies * key_len);
405
406 for (int i = 0; i < N_LENGTH_TESTS - 4; i++)
407 {
408 wrapper_x4 (k, bigdata0, bigdata1, bigdata2, bigdata3, r, r + 1, r + 2,
409 r + 3, i);
410 if (length_test_hashes[i] != r[0] || length_test_hashes[i] != r[1] ||
411 length_test_hashes[i] != r[2] || length_test_hashes[i] != r[3])
412 {
413 err = clib_error_return (
414 err,
415 "wrong length test hash x4 for length %u, "
416 "calculated { 0x%08x, 0x%08x, 0x%08x, 0x%08x }, expected 0x%08x",
417 i, r[0], r[1], r[2], r[3], length_test_hashes[i]);
418 goto done;
419 }
420 }
421
422done:
423 clib_toeplitz_hash_key_free (k);
Damjan Marion88019c42021-12-15 10:17:04 +0000424 return err;
425}
426
427void __test_perf_fn
Damjan Mariond5045e62022-04-06 21:16:37 +0200428perftest_fixed_12byte_x4 (test_perf_t *tp)
Damjan Marion88019c42021-12-15 10:17:04 +0000429{
430 u32 n = tp->n_ops / 4;
431 u8 *d0 = test_mem_alloc_and_splat (12, n, (void *) &ip4_tests[0].key);
432 u8 *d1 = test_mem_alloc_and_splat (12, n, (void *) &ip4_tests[1].key);
433 u8 *d2 = test_mem_alloc_and_splat (12, n, (void *) &ip4_tests[2].key);
434 u8 *d3 = test_mem_alloc_and_splat (12, n, (void *) &ip4_tests[3].key);
435 u32 *h0 = test_mem_alloc (4 * n);
436 u32 *h1 = test_mem_alloc (4 * n);
437 u32 *h2 = test_mem_alloc (4 * n);
438 u32 *h3 = test_mem_alloc (4 * n);
439 clib_toeplitz_hash_key_t *k = clib_toeplitz_hash_key_init (0, 0);
440
Damjan Mariond5045e62022-04-06 21:16:37 +0200441 test_perf_event_enable (tp);
Damjan Marion88019c42021-12-15 10:17:04 +0000442 for (int i = 0; i < n; i++)
443 clib_toeplitz_hash_x4 (k, d0 + i * 12, d1 + i * 12, d2 + i * 12,
444 d3 + i * 12, h0 + i, h1 + i, h2 + i, h3 + i, 12);
Damjan Mariond5045e62022-04-06 21:16:37 +0200445 test_perf_event_disable (tp);
Damjan Marion88019c42021-12-15 10:17:04 +0000446
447 clib_toeplitz_hash_key_free (k);
Damjan Marion88019c42021-12-15 10:17:04 +0000448}
449
450void __test_perf_fn
Damjan Mariond5045e62022-04-06 21:16:37 +0200451perftest_fixed_36byte_x4 (test_perf_t *tp)
Damjan Marion88019c42021-12-15 10:17:04 +0000452{
453 u32 n = tp->n_ops / 4;
454 u8 *d0 = test_mem_alloc_and_splat (36, n, (void *) &ip4_tests[0].key);
455 u8 *d1 = test_mem_alloc_and_splat (36, n, (void *) &ip4_tests[1].key);
456 u8 *d2 = test_mem_alloc_and_splat (36, n, (void *) &ip4_tests[2].key);
457 u8 *d3 = test_mem_alloc_and_splat (36, n, (void *) &ip4_tests[3].key);
458 u32 *h0 = test_mem_alloc (4 * n);
459 u32 *h1 = test_mem_alloc (4 * n);
460 u32 *h2 = test_mem_alloc (4 * n);
461 u32 *h3 = test_mem_alloc (4 * n);
462 clib_toeplitz_hash_key_t *k = clib_toeplitz_hash_key_init (0, 0);
463
Damjan Mariond5045e62022-04-06 21:16:37 +0200464 test_perf_event_enable (tp);
Damjan Marion88019c42021-12-15 10:17:04 +0000465 for (int i = 0; i < n; i++)
466 clib_toeplitz_hash_x4 (k, d0 + i * 36, d1 + i * 36, d2 + i * 36,
467 d3 + i * 36, h0 + i, h1 + i, h2 + i, h3 + i, 36);
Damjan Mariond5045e62022-04-06 21:16:37 +0200468 test_perf_event_disable (tp);
Damjan Marion88019c42021-12-15 10:17:04 +0000469
470 clib_toeplitz_hash_key_free (k);
Damjan Marion88019c42021-12-15 10:17:04 +0000471}
472
473void __test_perf_fn
Damjan Mariond5045e62022-04-06 21:16:37 +0200474perftest_variable_size_x4 (test_perf_t *tp)
Damjan Marion88019c42021-12-15 10:17:04 +0000475{
476 u32 key_len, n_keys, n = tp->n_ops / 4;
477 u8 *key;
478 u8 *d0 = test_mem_alloc (n);
479 u8 *d1 = test_mem_alloc (n);
480 u8 *d2 = test_mem_alloc (n);
481 u8 *d3 = test_mem_alloc (n);
482 u32 *h0 = test_mem_alloc (sizeof (u32));
483 u32 *h1 = test_mem_alloc (sizeof (u32));
484 u32 *h2 = test_mem_alloc (sizeof (u32));
485 u32 *h3 = test_mem_alloc (sizeof (u32));
486 clib_toeplitz_hash_key_t *k = clib_toeplitz_hash_key_init (0, 0);
487
488 k = clib_toeplitz_hash_key_init (0, 0);
489 key_len = k->key_length;
490 n_keys = ((n + 4) / k->key_length) + 1;
491 key = test_mem_alloc_and_splat (n_keys, key_len, k->data);
492 clib_toeplitz_hash_key_free (k);
493 k = clib_toeplitz_hash_key_init (key, key_len * n_keys);
494
Damjan Mariond5045e62022-04-06 21:16:37 +0200495 test_perf_event_enable (tp);
Damjan Marion88019c42021-12-15 10:17:04 +0000496 clib_toeplitz_hash_x4 (k, d0, d1, d2, d3, h0, h1, h2, h3, n);
Damjan Mariond5045e62022-04-06 21:16:37 +0200497 test_perf_event_disable (tp);
Damjan Marion88019c42021-12-15 10:17:04 +0000498
499 clib_toeplitz_hash_key_free (k);
Damjan Marion88019c42021-12-15 10:17:04 +0000500}
501
502REGISTER_TEST (clib_toeplitz_hash_x4) = {
503 .name = "clib_toeplitz_hash_x4",
504 .fn = test_clib_toeplitz_hash_x4,
Damjan Mariond5045e62022-04-06 21:16:37 +0200505 .perf_tests = PERF_TESTS ({ .name = "fixed (per 12 byte tuple)",
Damjan Marion88019c42021-12-15 10:17:04 +0000506 .n_ops = 1024,
507 .fn = perftest_fixed_12byte_x4 },
Damjan Mariond5045e62022-04-06 21:16:37 +0200508 { .name = "fixed (per 36 byte tuple)",
Damjan Marion88019c42021-12-15 10:17:04 +0000509 .n_ops = 1024,
510 .fn = perftest_fixed_36byte_x4 },
Damjan Mariond5045e62022-04-06 21:16:37 +0200511 { .name = "variable size (per byte)",
Damjan Marion88019c42021-12-15 10:17:04 +0000512 .n_ops = 16384,
513 .fn = perftest_variable_size_x4 }),
514};