]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/intel-ipsec-mb/LibPerfApp/ipsec_perf.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / intel-ipsec-mb / LibPerfApp / ipsec_perf.c
CommitLineData
11fdf7f2 1/**********************************************************************
f67539c2 2 Copyright(c) 2017-2019, Intel Corporation All rights reserved.
11fdf7f2
TL
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in
11 the documentation and/or other materials provided with the
12 distribution.
13 * Neither the name of Intel Corporation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28**********************************************************************/
29
30#include <stdio.h>
31#include <stdlib.h>
f67539c2 32#include <inttypes.h>
11fdf7f2
TL
33#include <string.h>
34#include <errno.h>
9f95a23c 35#include <malloc.h> /* memalign() or _aligned_malloc()/aligned_free() */
11fdf7f2
TL
36
37#ifdef _WIN32
38#include <windows.h>
39#include <process.h>
40#include <intrin.h>
f67539c2 41#define strdup _strdup
11fdf7f2
TL
42#define __forceinline static __forceinline
43#else
44#include <x86intrin.h>
45#define __forceinline static inline __attribute__((always_inline))
46#include <unistd.h>
47#include <pthread.h>
48#include <sched.h>
49#endif
50
51#include <intel-ipsec-mb.h>
52
53#include "msr.h"
54
f67539c2 55/* memory size for test buffers */
11fdf7f2 56#define BUFSIZE (512 * 1024 * 1024)
f67539c2
TL
57/* maximum size of a test buffer */
58#define JOB_SIZE_TOP (16 * 1024)
59/* min size of a buffer when testing range of buffers */
60#define DEFAULT_JOB_SIZE_MIN 16
61/* max size of a buffer when testing range of buffers */
62#define DEFAULT_JOB_SIZE_MAX (2 * 1024)
63/* number of bytes to increase buffer size when testing range of buffers */
64#define DEFAULT_JOB_SIZE_STEP 16
65/* max offset applied to a buffer - this is to avoid collisions in L1 */
66#define MAX_BUFFER_OFFSET 4096
67/* max value of sha_size_incr */
68#define MAX_SHA_SIZE_INCR 128
69/* region size for one buffer rounded up to 4K page size */
70#define REGION_SIZE (((JOB_SIZE_TOP + (MAX_BUFFER_OFFSET + \
71 MAX_SHA_SIZE_INCR)) + 4095) & (~4095))
72/* number of test buffers */
11fdf7f2
TL
73#define NUM_OFFSETS (BUFSIZE / REGION_SIZE)
74#define NUM_RUNS 16
f67539c2 75/* maximum number of 128-bit expanded keys */
11fdf7f2 76#define KEYS_PER_JOB 15
9f95a23c 77
f67539c2
TL
78#define AAD_SIZE_MAX JOB_SIZE_TOP
79#define CCM_AAD_SIZE_MAX 46
80#define DEFAULT_GCM_AAD_SIZE 12
81#define DEFAULT_CCM_AAD_SIZE 8
82
9f95a23c
TL
83#define ITER_SCALE_SMOKE 2048
84#define ITER_SCALE_SHORT 200000
85#define ITER_SCALE_LONG 2000000
86
11fdf7f2
TL
87#define BITS(x) (sizeof(x) * 8)
88#define DIM(x) (sizeof(x)/sizeof(x[0]))
89
11fdf7f2
TL
90#define MAX_NUM_THREADS 16 /* Maximum number of threads that can be created */
91
f67539c2
TL
92#define CIPHER_MODES_AES 7 /* CBC, CNTR, CNTR+8, CNTR_BITLEN,
93 CNTR_BITLEN-4, ECB, NULL_CIPHER */
11fdf7f2
TL
94#define CIPHER_MODES_DOCSIS 4 /* AES DOCSIS, AES DOCSIS+8, DES DOCSIS,
95 DES DOCSIS+8 */
96#define CIPHER_MODES_DES 1 /* DES */
97#define CIPHER_MODES_GCM 1 /* GCM */
98#define CIPHER_MODES_CCM 1 /* CCM */
99#define CIPHER_MODES_3DES 1 /* 3DES */
f67539c2 100#define CIPHER_MODES_PON 2 /* PON, NO_CTR PON */
11fdf7f2 101#define DIRECTIONS 2 /* ENC, DEC */
f67539c2
TL
102#define HASH_ALGS_AES 10 /* SHA1, SHA256, SHA224, SHA384, SHA512, XCBC,
103 MD5, NULL_HASH, CMAC, CMAC_BITLEN */
11fdf7f2
TL
104#define HASH_ALGS_DOCSIS 1 /* NULL_HASH */
105#define HASH_ALGS_GCM 1 /* GCM */
106#define HASH_ALGS_CCM 1 /* CCM */
107#define HASH_ALGS_DES 1 /* NULL_HASH for DES */
108#define HASH_ALGS_3DES 1 /* NULL_HASH for 3DES */
f67539c2 109#define HASH_ALGS_PON 1 /* CRC32/BIP for PON */
11fdf7f2
TL
110#define KEY_SIZES_AES 3 /* 16, 24, 32 */
111#define KEY_SIZES_DOCSIS 1 /* 16 or 8 */
112#define KEY_SIZES_GCM 3 /* 16, 24, 32 */
113#define KEY_SIZES_CCM 1 /* 16 */
114#define KEY_SIZES_DES 1 /* 8 */
115#define KEY_SIZES_3DES 1 /* 8 x 3 */
f67539c2 116#define KEY_SIZES_PON 1 /* 16 */
11fdf7f2
TL
117
118#define IA32_MSR_FIXED_CTR_CTRL 0x38D
119#define IA32_MSR_PERF_GLOBAL_CTR 0x38F
120#define IA32_MSR_CPU_UNHALTED_THREAD 0x30A
121
122/* Those defines tell how many different test cases are to be performed.
123 * Have to be multiplied by number of chosen architectures.
124 */
125#define VARIANTS_PER_ARCH_AES (CIPHER_MODES_AES * DIRECTIONS * \
126 HASH_ALGS_AES * KEY_SIZES_AES)
127#define VARIANTS_PER_ARCH_DOCSIS (CIPHER_MODES_DOCSIS * DIRECTIONS * \
128 HASH_ALGS_DOCSIS * KEY_SIZES_DOCSIS)
129#define VARIANTS_PER_ARCH_GCM (CIPHER_MODES_GCM * DIRECTIONS * \
130 HASH_ALGS_GCM * KEY_SIZES_GCM)
131#define VARIANTS_PER_ARCH_CCM (CIPHER_MODES_CCM * DIRECTIONS * \
132 HASH_ALGS_CCM * KEY_SIZES_CCM)
133#define VARIANTS_PER_ARCH_DES (CIPHER_MODES_DES * DIRECTIONS * \
134 HASH_ALGS_DES * KEY_SIZES_DES)
135#define VARIANTS_PER_ARCH_3DES (CIPHER_MODES_3DES * DIRECTIONS * \
136 HASH_ALGS_3DES * KEY_SIZES_3DES)
f67539c2
TL
137#define VARIANTS_PER_ARCH_PON (CIPHER_MODES_PON * DIRECTIONS * \
138 HASH_ALGS_PON * KEY_SIZES_PON)
11fdf7f2 139
11fdf7f2
TL
140enum arch_type_e {
141 ARCH_SSE = 0,
142 ARCH_AVX,
143 ARCH_AVX2,
f67539c2
TL
144 ARCH_AVX512,
145 NUM_ARCHS
11fdf7f2
TL
146};
147
148enum test_type_e {
149 TTYPE_AES_HMAC,
150 TTYPE_AES_DOCSIS,
151 TTYPE_AES_GCM,
152 TTYPE_AES_CCM,
153 TTYPE_AES_DES,
f67539c2
TL
154 TTYPE_AES_3DES,
155 TTYPE_PON,
156 TTYPE_CUSTOM,
157 NUM_TTYPES
11fdf7f2
TL
158};
159
f67539c2
TL
160/* This enum will be mostly translated to JOB_CIPHER_MODE
161 * (make sure to update c_mode_names list in print_times function) */
11fdf7f2
TL
162enum test_cipher_mode_e {
163 TEST_CBC = 1,
164 TEST_CNTR,
165 TEST_CNTR8, /* CNTR with increased buffer by 8 */
f67539c2
TL
166 TEST_CNTR_BITLEN, /* CNTR-BITLEN */
167 TEST_CNTR_BITLEN4, /* CNTR-BITLEN with 4 less bits in the last byte */
168 TEST_ECB,
11fdf7f2
TL
169 TEST_NULL_CIPHER,
170 TEST_AESDOCSIS,
171 TEST_AESDOCSIS8, /* AES DOCSIS with increased buffer size by 8 */
172 TEST_DESDOCSIS,
173 TEST_DESDOCSIS4, /* DES DOCSIS with increased buffer size by 4 */
174 TEST_GCM, /* Additional field used by GCM, not translated */
175 TEST_CCM,
176 TEST_DES,
177 TEST_3DES,
f67539c2
TL
178 TEST_PON_CNTR,
179 TEST_PON_NO_CNTR,
180 TEST_NUM_CIPHER_TESTS
11fdf7f2
TL
181};
182
f67539c2
TL
183/* This enum will be mostly translated to JOB_HASH_ALG
184 * (make sure to update h_alg_names list in print_times function) */
11fdf7f2
TL
185enum test_hash_alg_e {
186 TEST_SHA1 = 1,
187 TEST_SHA_224,
188 TEST_SHA_256,
189 TEST_SHA_384,
190 TEST_SHA_512,
191 TEST_XCBC,
192 TEST_MD5,
193 TEST_HASH_CMAC, /* added here to be included in AES tests */
f67539c2 194 TEST_HASH_CMAC_BITLEN,
11fdf7f2
TL
195 TEST_NULL_HASH,
196 TEST_HASH_GCM, /* Additional field used by GCM, not translated */
197 TEST_CUSTOM_HASH, /* unused */
f67539c2
TL
198 TEST_HASH_CCM,
199 TEST_PON_CRC_BIP,
200 TEST_NUM_HASH_TESTS
11fdf7f2
TL
201};
202
203/* Struct storing cipher parameters */
204struct params_s {
205 JOB_CIPHER_DIRECTION cipher_dir;
206 enum test_type_e test_type; /* AES, DOCSIS, GCM */
207 enum test_cipher_mode_e cipher_mode;
208 enum test_hash_alg_e hash_alg;
209 uint32_t aes_key_size;
210 uint32_t size_aes;
f67539c2 211 uint64_t aad_size;
11fdf7f2
TL
212 uint32_t num_sizes;
213 uint32_t num_variants;
214 uint32_t core;
215};
216
f67539c2
TL
217struct custom_job_params {
218 enum test_cipher_mode_e cipher_mode;
219 enum test_hash_alg_e hash_alg;
220 uint32_t aes_key_size;
221 JOB_CIPHER_DIRECTION cipher_dir;
222};
223
224union params {
225 enum arch_type_e arch_type;
226 struct custom_job_params job_params;
227};
228
229struct str_value_mapping {
230 const char *name;
231 union params values;
232};
233
234struct str_value_mapping arch_str_map[] = {
235 {.name = "SSE", .values.arch_type = ARCH_SSE },
236 {.name = "AVX", .values.arch_type = ARCH_AVX },
237 {.name = "AVX2", .values.arch_type = ARCH_AVX2 },
238 {.name = "AVX512", .values.arch_type = ARCH_AVX512 }
239};
240
241struct str_value_mapping cipher_algo_str_map[] = {
242 {
243 .name = "aes-cbc-128",
244 .values.job_params = {
245 .cipher_mode = TEST_CBC,
246 .aes_key_size = AES_128_BYTES
247 }
248 },
249 {
250 .name = "aes-cbc-192",
251 .values.job_params = {
252 .cipher_mode = TEST_CBC,
253 .aes_key_size = AES_192_BYTES
254 }
255 },
256 {
257 .name = "aes-cbc-256",
258 .values.job_params = {
259 .cipher_mode = TEST_CBC,
260 .aes_key_size = AES_256_BYTES
261 }
262 },
263 {
264 .name = "aes-ctr-128",
265 .values.job_params = {
266 .cipher_mode = TEST_CNTR,
267 .aes_key_size = AES_128_BYTES
268 }
269 },
270 {
271 .name = "aes-ctr-192",
272 .values.job_params = {
273 .cipher_mode = TEST_CNTR,
274 .aes_key_size = AES_192_BYTES
275 }
276 },
277 {
278 .name = "aes-ctr-256",
279 .values.job_params = {
280 .cipher_mode = TEST_CNTR,
281 .aes_key_size = AES_256_BYTES
282 }
283 },
284 {
285 .name = "aes-ctr8-128",
286 .values.job_params = {
287 .cipher_mode = TEST_CNTR8,
288 .aes_key_size = AES_128_BYTES
289 }
290 },
291 {
292 .name = "aes-ctr8-192",
293 .values.job_params = {
294 .cipher_mode = TEST_CNTR8,
295 .aes_key_size = AES_192_BYTES
296 }
297 },
298 {
299 .name = "aes-ctr8-256",
300 .values.job_params = {
301 .cipher_mode = TEST_CNTR8,
302 .aes_key_size = AES_256_BYTES
303 }
304 },
305 {
306 .name = "aes-ctr-bit-128",
307 .values.job_params = {
308 .cipher_mode = TEST_CNTR_BITLEN,
309 .aes_key_size = AES_128_BYTES
310 }
311 },
312 {
313 .name = "aes-ctr-bit-192",
314 .values.job_params = {
315 .cipher_mode = TEST_CNTR_BITLEN,
316 .aes_key_size = AES_192_BYTES
317 }
318 },
319 {
320 .name = "aes-ctr-bit-256",
321 .values.job_params = {
322 .cipher_mode = TEST_CNTR_BITLEN,
323 .aes_key_size = AES_256_BYTES
324 }
325 },
326 {
327 .name = "aes-ctr-bit4-128",
328 .values.job_params = {
329 .cipher_mode = TEST_CNTR_BITLEN4,
330 .aes_key_size = AES_128_BYTES
331 }
332 },
333 {
334 .name = "aes-ctr-bit4-192",
335 .values.job_params = {
336 .cipher_mode = TEST_CNTR_BITLEN4,
337 .aes_key_size = AES_192_BYTES
338 }
339 },
340 {
341 .name = "aes-ctr-bit4-256",
342 .values.job_params = {
343 .cipher_mode = TEST_CNTR_BITLEN4,
344 .aes_key_size = AES_256_BYTES
345 }
346 },
347 {
348 .name = "aes-ecb-128",
349 .values.job_params = {
350 .cipher_mode = TEST_ECB,
351 .aes_key_size = AES_128_BYTES
352 }
353 },
354 {
355 .name = "aes-ecb-192",
356 .values.job_params = {
357 .cipher_mode = TEST_ECB,
358 .aes_key_size = AES_192_BYTES
359 }
360 },
361 {
362 .name = "aes-ecb-256",
363 .values.job_params = {
364 .cipher_mode = TEST_ECB,
365 .aes_key_size = AES_256_BYTES
366 }
367 },
368 {
369 .name = "aes-docsis",
370 .values.job_params = {
371 .cipher_mode = TEST_AESDOCSIS,
372 .aes_key_size = AES_128_BYTES
373 }
374 },
375 {
376 .name = "aes-docsis8",
377 .values.job_params = {
378 .cipher_mode = TEST_AESDOCSIS8,
379 .aes_key_size = AES_128_BYTES
380 }
381 },
382 {
383 .name = "des-docsis",
384 .values.job_params = {
385 .cipher_mode = TEST_DESDOCSIS,
386 .aes_key_size = 8
387 }
388 },
389 {
390 .name = "des-docsis4",
391 .values.job_params = {
392 .cipher_mode = TEST_DESDOCSIS4,
393 .aes_key_size = 8
394 }
395 },
396 {
397 .name = "des-cbc",
398 .values.job_params = {
399 .cipher_mode = TEST_DES,
400 .aes_key_size = 8
401 }
402 },
403 {
404 .name = "3des-cbc",
405 .values.job_params = {
406 .cipher_mode = TEST_3DES,
407 .aes_key_size = 8
408 }
409 },
410 {
411 .name = "null",
412 .values.job_params = {
413 .cipher_mode = TEST_NULL_CIPHER,
414 .aes_key_size = 0
415 }
416 }
417};
418
419struct str_value_mapping hash_algo_str_map[] = {
420 {
421 .name = "sha1-hmac",
422 .values.job_params = {
423 .hash_alg = TEST_SHA1
424 }
425 },
426 {
427 .name = "sha224-hmac",
428 .values.job_params = {
429 .hash_alg = TEST_SHA_224
430 }
431 },
432 {
433 .name = "sha256-hmac",
434 .values.job_params = {
435 .hash_alg = TEST_SHA_256
436 }
437 },
438 {
439 .name = "sha384-hmac",
440 .values.job_params = {
441 .hash_alg = TEST_SHA_384
442 }
443 },
444 {
445 .name = "sha512-hmac",
446 .values.job_params = {
447 .hash_alg = TEST_SHA_512
448 }
449 },
450 {
451 .name = "aes-xcbc",
452 .values.job_params = {
453 .hash_alg = TEST_XCBC
454 }
455 },
456 {
457 .name = "md5-hmac",
458 .values.job_params = {
459 .hash_alg = TEST_MD5
460 }
461 },
462 {
463 .name = "aes-cmac",
464 .values.job_params = {
465 .hash_alg = TEST_HASH_CMAC
466 }
467 },
468 {
469 .name = "null",
470 .values.job_params = {
471 .hash_alg = TEST_NULL_HASH
472 }
473 },
474 {
475 .name = "aes-cmac-bitlen",
476 .values.job_params = {
477 .hash_alg = TEST_HASH_CMAC_BITLEN
478 }
479 },
480};
481
482struct str_value_mapping aead_algo_str_map[] = {
483 {
484 .name = "aes-gcm-128",
485 .values.job_params = {
486 .cipher_mode = TEST_GCM,
487 .hash_alg = TEST_HASH_GCM,
488 .aes_key_size = AES_128_BYTES
489 }
490 },
491 {
492 .name = "aes-gcm-192",
493 .values.job_params = {
494 .cipher_mode = TEST_GCM,
495 .hash_alg = TEST_HASH_GCM,
496 .aes_key_size = AES_192_BYTES
497 }
498 },
499 {
500 .name = "aes-gcm-256",
501 .values.job_params = {
502 .cipher_mode = TEST_GCM,
503 .hash_alg = TEST_HASH_GCM,
504 .aes_key_size = AES_256_BYTES
505 }
506 },
507 {
508 .name = "aes-ccm-128",
509 .values.job_params = {
510 .cipher_mode = TEST_CCM,
511 .hash_alg = TEST_HASH_CCM,
512 .aes_key_size = AES_128_BYTES
513 }
514 },
515 {
516 .name = "pon-128",
517 .values.job_params = {
518 .cipher_mode = TEST_PON_CNTR,
519 .hash_alg = TEST_PON_CRC_BIP,
520 .aes_key_size = AES_128_BYTES
521 }
522 },
523 {
524 .name = "pon-128-no-ctr",
525 .values.job_params = {
526 .cipher_mode = TEST_PON_NO_CNTR,
527 .hash_alg = TEST_PON_CRC_BIP,
528 .aes_key_size = 0
529 }
530 },
531};
532
533struct str_value_mapping cipher_dir_str_map[] = {
534 {.name = "encrypt", .values.job_params.cipher_dir = ENCRYPT},
535 {.name = "decrypt", .values.job_params.cipher_dir = DECRYPT}
536};
537
11fdf7f2
TL
538/* This struct stores all information about performed test case */
539struct variant_s {
540 uint32_t arch;
541 struct params_s params;
542 uint64_t *avg_times;
543};
544
545/* Struct storing information to be passed to threads */
546struct thread_info {
547 int print_info;
548 int core;
9f95a23c 549 MB_MGR *p_mgr;
11fdf7f2
TL
550} t_info[MAX_NUM_THREADS];
551
552enum cache_type_e {
553 WARM = 0,
554 COLD = 1
555};
556
11fdf7f2 557enum cache_type_e cache_type = WARM;
f67539c2
TL
558
559const uint32_t auth_tag_length_bytes[19] = {
560 12, /* SHA1 */
561 14, /* SHA_224 */
562 16, /* SHA_256 */
563 24, /* SHA_384 */
564 32, /* SHA_512 */
565 12, /* AES_XCBC */
566 12, /* MD5 */
567 0, /* NULL_HASH */
568#ifndef NO_GCM
569 16, /* AES_GMAC */
570#endif
571 0, /* CUSTOM HASH */
572 0, /* AES_CCM */
573 16, /* AES_CMAC */
574 20, /* PLAIN_SHA1 */
575 28, /* PLAIN_SHA_224 */
576 32, /* PLAIN_SHA_256 */
577 48, /* PLAIN_SHA_384 */
578 64, /* PLAIN_SHA_512 */
579 4, /* AES_CMAC_BITLEN (3GPP) */
580 8, /* PON */
11fdf7f2 581};
11fdf7f2 582uint32_t index_limit;
11fdf7f2
TL
583uint32_t key_idxs[NUM_OFFSETS];
584uint32_t offsets[NUM_OFFSETS];
f67539c2
TL
585uint32_t sha_size_incr = 24;
586
587enum range {
588 RANGE_MIN = 0,
589 RANGE_STEP,
590 RANGE_MAX,
591 NUM_RANGE
592};
593
594uint32_t job_sizes[NUM_RANGE] = {DEFAULT_JOB_SIZE_MIN,
595 DEFAULT_JOB_SIZE_STEP,
596 DEFAULT_JOB_SIZE_MAX};
597uint32_t job_iter = 0;
598uint64_t gcm_aad_size = DEFAULT_GCM_AAD_SIZE;
599uint64_t ccm_aad_size = DEFAULT_CCM_AAD_SIZE;
600
601struct custom_job_params custom_job_params = {
602 .cipher_mode = TEST_NULL_CIPHER,
603 .hash_alg = TEST_NULL_HASH,
604 .aes_key_size = 0,
605 .cipher_dir = ENCRYPT
606};
11fdf7f2
TL
607
608uint8_t archs[NUM_ARCHS] = {1, 1, 1, 1}; /* uses all function sets */
f67539c2
TL
609/* AES, DOCSIS, GCM, CCM, DES, 3DES, PON, CUSTOM */
610uint8_t test_types[NUM_TTYPES] = {1, 1, 1, 1, 1, 1, 1, 0};
11fdf7f2
TL
611
612int use_gcm_job_api = 0;
613int use_unhalted_cycles = 0; /* read unhalted cycles instead of tsc */
614uint64_t rd_cycles_cost = 0; /* cost of reading unhalted cycles */
615uint64_t core_mask = 0; /* bitmap of selected cores */
616
617uint64_t flags = 0; /* flags passed to alloc_mb_mgr() */
618
9f95a23c 619uint32_t iter_scale = ITER_SCALE_LONG;
11fdf7f2 620
f67539c2
TL
621#define PB_INIT_SIZE 50
622#define PB_INIT_IDX 2 /* after \r and [ */
623static uint32_t PB_SIZE = PB_INIT_SIZE;
624static uint32_t PB_FINAL_IDX = (PB_INIT_SIZE + (PB_INIT_IDX - 1));
625static char prog_bar[PB_INIT_SIZE + 4]; /* 50 + 4 for \r, [, ], \0 */
626static uint32_t pb_idx = PB_INIT_IDX;
627static uint32_t pb_mod = 0;
628
629static int silent_progress_bar = 0;
630
631static void prog_bar_init(const uint32_t total_num)
632{
633 if (silent_progress_bar)
634 return;
635
636 if (total_num < PB_SIZE) {
637 PB_SIZE = total_num;
638 PB_FINAL_IDX = (PB_SIZE + (PB_INIT_IDX - 1));
639 }
640 pb_idx = PB_INIT_IDX;
641 pb_mod = total_num / PB_SIZE;
642
643 /* 32 dec == ascii ' ' char */
644 memset(prog_bar, 32, sizeof(prog_bar));
645 prog_bar[0] = '\r';
646 prog_bar[1] = '[';
647 prog_bar[PB_FINAL_IDX + 1] = ']';
648 prog_bar[PB_FINAL_IDX + 2] = '\0';
649
650 fputs(prog_bar, stderr);
651}
652
653static void prog_bar_fini(void)
654{
655 if (silent_progress_bar)
656 return;
657
658 prog_bar[PB_FINAL_IDX] = 'X'; /* set final X */
659 fputs(prog_bar, stderr);
660}
661
662static void prog_bar_update(const uint32_t num)
663{
664 if (silent_progress_bar)
665 return;
666
667 if ((pb_mod == 0) || num % pb_mod == 0) {
668 /* print X at every ~50th variant */
669 prog_bar[pb_idx] = 'X';
670 fputs(prog_bar, stderr);
671
672 /* don't overrun final idx */
673 if (pb_idx < (PB_SIZE + 1))
674 pb_idx++;
675 } else {
676 const char pb_inter_chars[] = {'|', '/', '-', '\\'};
677 /* print intermediate chars */
678 prog_bar[pb_idx] = pb_inter_chars[num % DIM(pb_inter_chars)];
679 fputs(prog_bar, stderr);
680 }
681}
682
11fdf7f2 683/* Read unhalted cycles */
f67539c2 684__forceinline uint64_t read_cycles(const uint32_t core)
11fdf7f2
TL
685{
686 uint64_t val = 0;
687
688 if (msr_read(core, IA32_MSR_CPU_UNHALTED_THREAD,
689 &val) != MACHINE_RETVAL_OK) {
690 fprintf(stderr, "Error reading cycles "
691 "counter on core %u!\n", core);
692 exit(EXIT_FAILURE);
693 }
694
695 return val;
696}
697
f67539c2
TL
698/* Method used by qsort to compare 2 values */
699static int compare_uint64_t(const void *a, const void *b)
11fdf7f2 700{
f67539c2 701 return (int)(int64_t)(*(const uint64_t *)a - *(const uint64_t *)b);
11fdf7f2
TL
702}
703
704/* Get number of bits set in value */
f67539c2 705static unsigned bitcount(const uint64_t val)
11fdf7f2 706{
f67539c2 707 unsigned i, bits = 0;
11fdf7f2
TL
708
709 for (i = 0; i < BITS(val); i++)
710 if (val & (1ULL << i))
711 bits++;
712
713 return bits;
714}
715
716/* Get the next core in core mask
717 Set last_core to negative to start from beginnig of core_mask */
718static int next_core(const uint64_t core_mask,
719 const int last_core)
720{
721 int core = 0;
722
723 if (last_core >= 0)
724 core = last_core;
725
726 while (((core_mask >> core) & 1) == 0) {
727 core++;
728
729 if (core >= (int)BITS(core_mask))
730 return -1;
731 }
732
733 return core;
734}
735
736/* Set CPU affinity for current thread */
737static int set_affinity(const int cpu)
738{
739 int ret = 0;
11fdf7f2
TL
740 int num_cpus = 0;
741
742 /* Get number of cpus in the system */
9f95a23c
TL
743#ifdef _WIN32
744 GROUP_AFFINITY NewGroupAffinity;
745
746 memset(&NewGroupAffinity, 0, sizeof(GROUP_AFFINITY));
747 num_cpus = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
748#else
11fdf7f2 749 num_cpus = sysconf(_SC_NPROCESSORS_CONF);
9f95a23c 750#endif
11fdf7f2
TL
751 if (num_cpus == 0) {
752 fprintf(stderr, "Zero processors in the system!");
753 return 1;
754 }
755
756 /* Check if selected core is valid */
757 if (cpu < 0 || cpu >= num_cpus) {
758 fprintf(stderr, "Invalid CPU selected! "
759 "Max valid CPU is %u\n", num_cpus - 1);
760 return 1;
761 }
762
9f95a23c
TL
763#ifdef _WIN32
764 NewGroupAffinity.Mask = 1ULL << cpu;
765 ret = !SetThreadGroupAffinity(GetCurrentThread(),
766 &NewGroupAffinity, NULL);
767#else
768 cpu_set_t cpuset;
769
11fdf7f2
TL
770 CPU_ZERO(&cpuset);
771 CPU_SET(cpu, &cpuset);
772
773 /* Set affinity of current process to cpu */
774 ret = sched_setaffinity(0, sizeof(cpuset), &cpuset);
775#endif /* _WIN32 */
9f95a23c 776
11fdf7f2
TL
777 return ret;
778}
779
780/* Start counting unhalted cycles */
f67539c2 781static int start_cycles_ctr(const uint32_t core)
11fdf7f2
TL
782{
783 int ret;
784
785 if (core >= BITS(core_mask))
786 return 1;
787
788 /* Disable cycles counter */
789 ret = msr_write(core, IA32_MSR_PERF_GLOBAL_CTR, 0);
790 if (ret != MACHINE_RETVAL_OK)
791 return ret;
792
793 /* Zero cycles counter */
794 ret = msr_write(core, IA32_MSR_CPU_UNHALTED_THREAD, 0);
795 if (ret != MACHINE_RETVAL_OK)
796 return ret;
797
798 /* Enable OS and user tracking in FixedCtr1 */
799 ret = msr_write(core, IA32_MSR_FIXED_CTR_CTRL, 0x30);
800 if (ret != MACHINE_RETVAL_OK)
801 return ret;
802
803 /* Enable cycles counter */
804 return msr_write(core, IA32_MSR_PERF_GLOBAL_CTR, (1ULL << 33));
805}
806
807/* Init MSR module */
808static int init_msr_mod(void)
809{
810 unsigned max_core_count = 0;
9f95a23c
TL
811#ifdef _WIN32
812 max_core_count = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
813#else
11fdf7f2 814 max_core_count = sysconf(_SC_NPROCESSORS_CONF);
9f95a23c 815#endif
11fdf7f2
TL
816 if (max_core_count == 0) {
817 fprintf(stderr, "Zero processors in the system!");
818 return MACHINE_RETVAL_ERROR;
819 }
9f95a23c 820
11fdf7f2
TL
821 return machine_init(max_core_count);
822}
823
824/* Set the cost of reading unhalted cycles using RDMSR */
825static int set_unhalted_cycle_cost(const int core, uint64_t *value)
826{
827 uint64_t time1, time2;
828
829 if (value == NULL || core < 0)
830 return 1;
831
832 time1 = read_cycles(core);
833 time2 = read_cycles(core);
834
835 /* Calculate delta */
836 *value = (time2 - time1);
837
838 return 0;
839}
840
841/* Calculate the general cost of reading unhalted cycles (median) */
842static int set_avg_unhalted_cycle_cost(const int core, uint64_t *value)
843{
844 unsigned i;
845 uint64_t cycles[10];
846
847 if (value == NULL || core_mask == 0 || core < 0)
848 return 1;
849
850 /* Fill cycles table with read cost values */
851 for (i = 0; i < DIM(cycles); i++)
852 if (set_unhalted_cycle_cost(core, &cycles[i]) != 0)
853 return 1;
854
855 /* sort array */
f67539c2 856 qsort(cycles, DIM(cycles), sizeof(uint64_t), compare_uint64_t);
11fdf7f2
TL
857
858 /* set median cost */
859 *value = cycles[DIM(cycles)/2];
860
861 return 0;
862}
863
864/* Freeing allocated memory */
f67539c2 865static void free_mem(uint8_t **p_buffer, uint128_t **p_keys)
11fdf7f2 866{
f67539c2
TL
867 uint128_t *keys = NULL;
868 uint8_t *buf = NULL;
869
870 if (p_keys != NULL) {
871 keys = *p_keys;
872 *p_keys = NULL;
873 }
874
875 if (p_buffer != NULL) {
876 buf = *p_buffer;
877 *p_buffer = NULL;
878 }
879
9f95a23c 880#ifdef LINUX
f67539c2
TL
881 if (keys != NULL)
882 free(keys);
9f95a23c 883
11fdf7f2
TL
884 if (buf != NULL)
885 free(buf);
9f95a23c 886#else
f67539c2
TL
887 if (keys != NULL)
888 _aligned_free(keys);
9f95a23c
TL
889
890 if (buf != NULL)
891 _aligned_free(buf);
892#endif
11fdf7f2
TL
893}
894
f67539c2
TL
895static const void *
896get_key_pointer(const uint32_t index, const uint128_t *p_keys)
897{
898 return (const void *) &p_keys[key_idxs[index]];
899}
900
901static uint8_t *get_src_buffer(const uint32_t index, uint8_t *p_buffer)
902{
903 return &p_buffer[offsets[index]];
904}
905
906static uint8_t *get_dst_buffer(const uint32_t index, uint8_t *p_buffer)
11fdf7f2 907{
f67539c2
TL
908 return &p_buffer[offsets[index] + sha_size_incr];
909}
910
911static uint32_t get_next_index(uint32_t index)
912{
913 if (++index >= index_limit)
914 index = 0;
915 return index;
916}
917
918static void init_buf(void *pb, const size_t length)
919{
920 const size_t n = length / sizeof(uint64_t);
921 size_t i = 0;
922
923 if (pb == NULL)
924 return;
925
926 for (i = 0; i < n; i++)
927 ((uint64_t *)pb)[i] = (uint64_t) rand();
928}
929
930/*
931 * Packet and key memory allocation and initialization.
932 * init_offsets() needs to be called prior to that so that
933 * index_limit is set up accordingly to hot/cold selection.
934 */
935static void init_mem(uint8_t **p_buffer, uint128_t **p_keys)
936{
937 const size_t bufs_size = index_limit * REGION_SIZE;
938 const size_t keys_size = index_limit * KEYS_PER_JOB * sizeof(uint128_t);
9f95a23c 939 const size_t alignment = 64;
f67539c2
TL
940 uint8_t *buf = NULL;
941 uint128_t *keys = NULL;
942
943 if (p_keys == NULL || p_buffer == NULL) {
944 fprintf(stderr, "Internal buffer allocation error!\n");
945 exit(EXIT_FAILURE);
946 }
11fdf7f2 947
9f95a23c
TL
948#ifdef LINUX
949 buf = (uint8_t *) memalign(alignment, bufs_size);
950#else
951 buf = (uint8_t *) _aligned_malloc(bufs_size, alignment);
952#endif
11fdf7f2
TL
953 if (!buf) {
954 fprintf(stderr, "Could not malloc buf\n");
955 exit(EXIT_FAILURE);
956 }
957
9f95a23c 958#ifdef LINUX
f67539c2 959 keys = (uint128_t *) memalign(alignment, keys_size);
9f95a23c 960#else
f67539c2 961 keys = (uint128_t *) _aligned_malloc(keys_size, alignment);
9f95a23c 962#endif
f67539c2
TL
963 if (!keys) {
964 fprintf(stderr, "Could not allocate memory for keys!\n");
965 free_mem(&buf, &keys);
11fdf7f2
TL
966 exit(EXIT_FAILURE);
967 }
968
f67539c2
TL
969 *p_keys = keys;
970 *p_buffer = buf;
11fdf7f2 971
f67539c2
TL
972 init_buf(buf, bufs_size);
973 init_buf(keys, keys_size);
974}
975
976/*
977 * Initialize packet buffer and keys offsets from
978 * the start of the respective buffers
979 */
980static void init_offsets(const enum cache_type_e ctype)
981{
11fdf7f2 982 if (ctype == COLD) {
f67539c2
TL
983 uint32_t i;
984
11fdf7f2 985 for (i = 0; i < NUM_OFFSETS; i++) {
f67539c2 986 offsets[i] = (i * REGION_SIZE) + (rand() & 0x3C0);
11fdf7f2
TL
987 key_idxs[i] = i * KEYS_PER_JOB;
988 }
9f95a23c 989
f67539c2
TL
990 /* swap the entries at random */
991 for (i = 0; i < NUM_OFFSETS; i++) {
992 const uint32_t swap_idx = (rand() % NUM_OFFSETS);
993 const uint32_t tmp_offset = offsets[swap_idx];
994 const uint32_t tmp_keyidx = key_idxs[swap_idx];
995
996 offsets[swap_idx] = offsets[i];
997 key_idxs[swap_idx] = key_idxs[i];
998 offsets[i] = tmp_offset;
999 key_idxs[i] = tmp_keyidx;
11fdf7f2 1000 }
f67539c2 1001
11fdf7f2 1002 index_limit = NUM_OFFSETS;
f67539c2
TL
1003 } else { /* WARM */
1004 uint32_t i;
1005
1006 index_limit = 16;
1007
1008 for (i = 0; i < index_limit; i++) {
1009 /*
1010 * Each buffer starts at different offset from
1011 * start of the page.
1012 * The most optimum determined difference between
1013 * offsets is 4 cache lines.
1014 */
1015 const uint32_t offset_step = (4 * 64);
1016 const uint32_t L1_way_size = 4096;
1017
1018 key_idxs[i] = i * KEYS_PER_JOB;
1019 offsets[i] = i * REGION_SIZE +
1020 ((i * offset_step) & (L1_way_size - 1));
11fdf7f2 1021 }
11fdf7f2
TL
1022 }
1023}
1024
f67539c2
TL
1025/*
1026 * This function translates enum test_ciper_mode_e to be used by ipsec_mb
11fdf7f2
TL
1027 * library
1028 */
f67539c2
TL
1029static JOB_CIPHER_MODE
1030translate_cipher_mode(const enum test_cipher_mode_e test_mode)
11fdf7f2
TL
1031{
1032 JOB_CIPHER_MODE c_mode = NULL_CIPHER;
1033
1034 switch (test_mode) {
1035 case TEST_CBC:
1036 c_mode = CBC;
1037 break;
1038 case TEST_CNTR:
1039 case TEST_CNTR8:
1040 c_mode = CNTR;
1041 break;
f67539c2
TL
1042 case TEST_CNTR_BITLEN:
1043 case TEST_CNTR_BITLEN4:
1044 c_mode = CNTR_BITLEN;
1045 break;
1046 case TEST_ECB:
1047 c_mode = ECB;
1048 break;
11fdf7f2
TL
1049 case TEST_NULL_CIPHER:
1050 c_mode = NULL_CIPHER;
1051 break;
1052 case TEST_AESDOCSIS:
1053 case TEST_AESDOCSIS8:
1054 c_mode = DOCSIS_SEC_BPI;
1055 break;
1056 case TEST_DESDOCSIS:
1057 case TEST_DESDOCSIS4:
1058 c_mode = DOCSIS_DES;
1059 break;
1060 case TEST_GCM:
1061 c_mode = GCM;
1062 break;
1063 case TEST_CCM:
1064 c_mode = CCM;
1065 break;
1066 case TEST_DES:
1067 c_mode = DES;
1068 break;
1069 case TEST_3DES:
1070 c_mode = DES3;
1071 break;
f67539c2
TL
1072 case TEST_PON_CNTR:
1073 case TEST_PON_NO_CNTR:
1074 c_mode = PON_AES_CNTR;
1075 break;
11fdf7f2
TL
1076 default:
1077 break;
1078 }
1079 return c_mode;
1080}
1081
1082/* Performs test using AES_HMAC or DOCSIS */
1083static uint64_t
9f95a23c 1084do_test(MB_MGR *mb_mgr, struct params_s *params,
f67539c2 1085 const uint32_t num_iter, uint8_t *p_buffer, uint128_t *p_keys)
11fdf7f2
TL
1086{
1087 JOB_AES_HMAC *job;
1088 JOB_AES_HMAC job_template;
1089 uint32_t i;
1090 static uint32_t index = 0;
1091 static DECLARE_ALIGNED(uint128_t iv, 16);
1092 static uint32_t ipad[5], opad[5], digest[3];
1093 static DECLARE_ALIGNED(uint32_t k1_expanded[11 * 4], 16);
1094 static DECLARE_ALIGNED(uint8_t k2[16], 16);
1095 static DECLARE_ALIGNED(uint8_t k3[16], 16);
9f95a23c 1096 static DECLARE_ALIGNED(struct gcm_key_data gdata_key, 512);
f67539c2 1097 uint64_t xgem_hdr = 0;
11fdf7f2
TL
1098 uint32_t size_aes;
1099 uint64_t time = 0;
1100 uint32_t aux;
1101
1102 if ((params->cipher_mode == TEST_AESDOCSIS8) ||
1103 (params->cipher_mode == TEST_CNTR8))
1104 size_aes = params->size_aes + 8;
1105 else if (params->cipher_mode == TEST_DESDOCSIS4)
1106 size_aes = params->size_aes + 4;
1107 else
1108 size_aes = params->size_aes;
1109
f67539c2
TL
1110 if (params->cipher_mode == TEST_CNTR_BITLEN)
1111 job_template.msg_len_to_cipher_in_bits = size_aes * 8;
1112 else if (params->cipher_mode == TEST_CNTR_BITLEN4)
1113 job_template.msg_len_to_cipher_in_bits = size_aes * 8 - 4;
1114 else
1115 job_template.msg_len_to_cipher_in_bytes = size_aes;
1116
11fdf7f2
TL
1117 job_template.msg_len_to_hash_in_bytes = size_aes + sha_size_incr;
1118 job_template.hash_start_src_offset_in_bytes = 0;
1119 job_template.cipher_start_src_offset_in_bytes = sha_size_incr;
1120 job_template.iv = (uint8_t *) &iv;
1121 job_template.iv_len_in_bytes = 16;
1122
1123 job_template.auth_tag_output = (uint8_t *) digest;
1124
1125 switch (params->hash_alg) {
1126 case TEST_XCBC:
1127 job_template.u.XCBC._k1_expanded = k1_expanded;
1128 job_template.u.XCBC._k2 = k2;
1129 job_template.u.XCBC._k3 = k3;
1130 job_template.hash_alg = AES_XCBC;
1131 break;
1132 case TEST_HASH_CCM:
1133 job_template.hash_alg = AES_CCM;
1134 break;
1135 case TEST_HASH_GCM:
1136 job_template.hash_alg = AES_GMAC;
1137 break;
1138 case TEST_NULL_HASH:
1139 job_template.hash_alg = NULL_HASH;
1140 break;
1141 case TEST_HASH_CMAC:
1142 job_template.u.CMAC._key_expanded = k1_expanded;
1143 job_template.u.CMAC._skey1 = k2;
1144 job_template.u.CMAC._skey2 = k3;
1145 job_template.hash_alg = AES_CMAC;
1146 break;
f67539c2
TL
1147 case TEST_HASH_CMAC_BITLEN:
1148 job_template.u.CMAC._key_expanded = k1_expanded;
1149 job_template.u.CMAC._skey1 = k2;
1150 job_template.u.CMAC._skey2 = k3;
1151 /*
1152 * CMAC bit level version is done in bits (length is
1153 * converted to bits and it is decreased by 4 bits,
1154 * to force the CMAC bitlen path)
1155 */
1156 job_template.msg_len_to_hash_in_bits =
1157 (job_template.msg_len_to_hash_in_bytes * 8) - 4;
1158 job_template.hash_alg = AES_CMAC_BITLEN;
1159 break;
1160 case TEST_PON_CRC_BIP:
1161 job_template.hash_alg = PON_CRC_BIP;
1162 job_template.msg_len_to_hash_in_bytes = size_aes + 8;
1163 job_template.cipher_start_src_offset_in_bytes = 8;
1164 if (params->cipher_mode == TEST_PON_NO_CNTR)
1165 job_template.msg_len_to_cipher_in_bytes = 0;
1166 break;
11fdf7f2
TL
1167 default:
1168 /* HMAC hash alg is SHA1 or MD5 */
1169 job_template.u.HMAC._hashed_auth_key_xor_ipad =
1170 (uint8_t *) ipad;
1171 job_template.u.HMAC._hashed_auth_key_xor_opad =
1172 (uint8_t *) opad;
1173 job_template.hash_alg = (JOB_HASH_ALG) params->hash_alg;
1174 break;
1175 }
1176 job_template.auth_tag_output_len_in_bytes =
1177 (uint64_t) auth_tag_length_bytes[job_template.hash_alg - 1];
1178
1179 job_template.cipher_direction = params->cipher_dir;
1180
1181 if (params->cipher_mode == TEST_NULL_CIPHER) {
1182 job_template.chain_order = HASH_CIPHER;
f67539c2
TL
1183 } else if (params->cipher_mode == TEST_CCM) {
1184 if (job_template.cipher_direction == ENCRYPT)
1185 job_template.chain_order = HASH_CIPHER;
1186 else
1187 job_template.chain_order = CIPHER_HASH;
11fdf7f2
TL
1188 } else {
1189 if (job_template.cipher_direction == ENCRYPT)
1190 job_template.chain_order = CIPHER_HASH;
1191 else
1192 job_template.chain_order = HASH_CIPHER;
1193 }
1194
1195 /* Translating enum to the API's one */
1196 job_template.cipher_mode = translate_cipher_mode(params->cipher_mode);
1197 job_template.aes_key_len_in_bytes = params->aes_key_size;
1198 if (job_template.cipher_mode == GCM) {
1199 uint8_t key[32];
1200
9f95a23c
TL
1201 switch (params->aes_key_size) {
1202 case AES_128_BYTES:
1203 IMB_AES128_GCM_PRE(mb_mgr, key, &gdata_key);
1204 break;
1205 case AES_192_BYTES:
1206 IMB_AES192_GCM_PRE(mb_mgr, key, &gdata_key);
1207 break;
1208 case AES_256_BYTES:
1209 default:
1210 IMB_AES256_GCM_PRE(mb_mgr, key, &gdata_key);
1211 break;
1212 }
11fdf7f2
TL
1213 job_template.aes_enc_key_expanded = &gdata_key;
1214 job_template.aes_dec_key_expanded = &gdata_key;
f67539c2 1215 job_template.u.GCM.aad_len_in_bytes = params->aad_size;
11fdf7f2
TL
1216 job_template.iv_len_in_bytes = 12;
1217 } else if (job_template.cipher_mode == CCM) {
1218 job_template.msg_len_to_cipher_in_bytes = size_aes;
1219 job_template.msg_len_to_hash_in_bytes = size_aes;
1220 job_template.hash_start_src_offset_in_bytes = 0;
1221 job_template.cipher_start_src_offset_in_bytes = 0;
f67539c2 1222 job_template.u.CCM.aad_len_in_bytes = params->aad_size;
11fdf7f2
TL
1223 job_template.iv_len_in_bytes = 13;
1224 } else if (job_template.cipher_mode == DES ||
11fdf7f2
TL
1225 job_template.cipher_mode == DOCSIS_DES) {
1226 job_template.aes_key_len_in_bytes = 8;
1227 job_template.iv_len_in_bytes = 8;
9f95a23c
TL
1228 } else if (job_template.cipher_mode == DES3) {
1229 job_template.aes_key_len_in_bytes = 24;
1230 job_template.iv_len_in_bytes = 8;
11fdf7f2
TL
1231 }
1232
f67539c2
TL
1233
1234 if (job_template.hash_alg == PON_CRC_BIP) {
1235 /* create XGEM header template */
1236 const uint64_t pli =
1237 (job_template.msg_len_to_cipher_in_bytes << 2) & 0xffff;
1238
1239 xgem_hdr = ((pli >> 8) & 0xff) | ((pli & 0xff) << 8);
1240 }
1241
11fdf7f2
TL
1242#ifndef _WIN32
1243 if (use_unhalted_cycles)
1244 time = read_cycles(params->core);
1245 else
1246#endif
1247 time = __rdtscp(&aux);
1248
1249 for (i = 0; i < num_iter; i++) {
9f95a23c 1250 job = IMB_GET_NEXT_JOB(mb_mgr);
11fdf7f2
TL
1251 *job = job_template;
1252
f67539c2
TL
1253 if (job->hash_alg == PON_CRC_BIP) {
1254 uint64_t *p_src =
1255 (uint64_t *) get_src_buffer(index, p_buffer);
1256
1257 job->src = (const uint8_t *)p_src;
1258 p_src[0] = xgem_hdr;
1259 } else {
1260 job->src = get_src_buffer(index, p_buffer);
1261 }
1262 job->dst = get_dst_buffer(index, p_buffer);
11fdf7f2
TL
1263 if (job->cipher_mode == GCM) {
1264 job->u.GCM.aad = job->src;
1265 } else if (job->cipher_mode == CCM) {
1266 job->u.CCM.aad = job->src;
1267 job->aes_enc_key_expanded = job->aes_dec_key_expanded =
f67539c2
TL
1268 (const uint32_t *) get_key_pointer(index,
1269 p_keys);
11fdf7f2
TL
1270 } else if (job->cipher_mode == DES3) {
1271 static const void *ks_ptr[3];
1272
1273 ks_ptr[0] = ks_ptr[1] = ks_ptr[2] =
f67539c2 1274 get_key_pointer(index, p_keys);
11fdf7f2
TL
1275 job->aes_enc_key_expanded =
1276 job->aes_dec_key_expanded = ks_ptr;
1277 } else {
1278 job->aes_enc_key_expanded = job->aes_dec_key_expanded =
f67539c2
TL
1279 (const uint32_t *) get_key_pointer(index,
1280 p_keys);
11fdf7f2
TL
1281 }
1282
f67539c2 1283 index = get_next_index(index);
9f95a23c
TL
1284#ifdef DEBUG
1285 job = IMB_SUBMIT_JOB(mb_mgr);
1286#else
1287 job = IMB_SUBMIT_JOB_NOCHECK(mb_mgr);
1288#endif
11fdf7f2
TL
1289 while (job) {
1290#ifdef DEBUG
1291 if (job->status != STS_COMPLETED)
1292 fprintf(stderr, "failed job, status:%d\n",
1293 job->status);
1294#endif
9f95a23c 1295 job = IMB_GET_COMPLETED_JOB(mb_mgr);
11fdf7f2
TL
1296 }
1297 }
1298
9f95a23c 1299 while ((job = IMB_FLUSH_JOB(mb_mgr))) {
11fdf7f2
TL
1300#ifdef DEBUG
1301 if (job->status != STS_COMPLETED)
1302 fprintf(stderr, "failed job, status:%d\n", job->status);
1303#endif
1304 }
1305
1306#ifndef _WIN32
1307 if (use_unhalted_cycles)
1308 time = (read_cycles(params->core) - rd_cycles_cost) - time;
1309 else
1310#endif
1311 time = __rdtscp(&aux) - time;
1312
1313 return time / num_iter;
1314}
1315
1316/* Performs test using GCM */
1317static uint64_t
9f95a23c 1318do_test_gcm(struct params_s *params,
f67539c2
TL
1319 const uint32_t num_iter, MB_MGR *mb_mgr,
1320 uint8_t *p_buffer, uint128_t *p_keys)
11fdf7f2 1321{
9f95a23c
TL
1322 static DECLARE_ALIGNED(struct gcm_key_data gdata_key, 512);
1323 static DECLARE_ALIGNED(struct gcm_context_data gdata_ctx, 64);
11fdf7f2
TL
1324 uint8_t *key;
1325 static uint32_t index = 0;
11fdf7f2
TL
1326 uint32_t size_aes = params->size_aes;
1327 uint32_t i;
f67539c2 1328 uint8_t *aad = NULL;
11fdf7f2
TL
1329 uint8_t auth_tag[12];
1330 DECLARE_ALIGNED(uint8_t iv[16], 16);
1331 uint64_t time = 0;
1332 uint32_t aux;
1333
1334 key = (uint8_t *) malloc(sizeof(uint8_t) * params->aes_key_size);
1335 if (!key) {
1336 fprintf(stderr, "Could not malloc key\n");
f67539c2
TL
1337 free_mem(&p_buffer, &p_keys);
1338 exit(EXIT_FAILURE);
1339 }
1340
1341 aad = (uint8_t *) malloc(sizeof(uint8_t) * params->aad_size);
1342 if (!aad) {
1343 free(key);
1344 fprintf(stderr, "Could not malloc AAD\n");
1345 free_mem(&p_buffer, &p_keys);
11fdf7f2
TL
1346 exit(EXIT_FAILURE);
1347 }
1348
9f95a23c
TL
1349 switch (params->aes_key_size) {
1350 case AES_128_BYTES:
1351 IMB_AES128_GCM_PRE(mb_mgr, key, &gdata_key);
1352 break;
1353 case AES_192_BYTES:
1354 IMB_AES192_GCM_PRE(mb_mgr, key, &gdata_key);
1355 break;
1356 case AES_256_BYTES:
1357 default:
1358 IMB_AES256_GCM_PRE(mb_mgr, key, &gdata_key);
1359 break;
1360 }
1361
11fdf7f2
TL
1362 if (params->cipher_dir == ENCRYPT) {
1363#ifndef _WIN32
1364 if (use_unhalted_cycles)
1365 time = read_cycles(params->core);
1366 else
1367#endif
1368 time = __rdtscp(&aux);
1369
9f95a23c
TL
1370 if (params->aes_key_size == AES_128_BYTES) {
1371 for (i = 0; i < num_iter; i++) {
f67539c2
TL
1372 uint8_t *pb = get_dst_buffer(index, p_buffer);
1373
9f95a23c
TL
1374 IMB_AES128_GCM_ENC(mb_mgr, &gdata_key,
1375 &gdata_ctx,
f67539c2
TL
1376 pb,
1377 pb,
9f95a23c 1378 size_aes, iv,
f67539c2 1379 aad, params->aad_size,
9f95a23c 1380 auth_tag, sizeof(auth_tag));
f67539c2 1381 index = get_next_index(index);
9f95a23c
TL
1382 }
1383 } else if (params->aes_key_size == AES_192_BYTES) {
1384 for (i = 0; i < num_iter; i++) {
f67539c2
TL
1385 uint8_t *pb = get_dst_buffer(index, p_buffer);
1386
9f95a23c
TL
1387 IMB_AES192_GCM_ENC(mb_mgr, &gdata_key,
1388 &gdata_ctx,
f67539c2
TL
1389 pb,
1390 pb,
9f95a23c 1391 size_aes, iv,
f67539c2 1392 aad, params->aad_size,
9f95a23c 1393 auth_tag, sizeof(auth_tag));
f67539c2 1394 index = get_next_index(index);
9f95a23c
TL
1395 }
1396 } else { /* 256 */
1397 for (i = 0; i < num_iter; i++) {
f67539c2
TL
1398 uint8_t *pb = get_dst_buffer(index, p_buffer);
1399
9f95a23c
TL
1400 IMB_AES256_GCM_ENC(mb_mgr, &gdata_key,
1401 &gdata_ctx,
f67539c2
TL
1402 pb,
1403 pb,
9f95a23c 1404 size_aes, iv,
f67539c2 1405 aad, params->aad_size,
9f95a23c 1406 auth_tag, sizeof(auth_tag));
f67539c2 1407 index = get_next_index(index);
9f95a23c 1408 }
11fdf7f2
TL
1409 }
1410#ifndef _WIN32
1411 if (use_unhalted_cycles)
1412 time = (read_cycles(params->core) -
1413 rd_cycles_cost) - time;
1414 else
1415#endif
1416 time = __rdtscp(&aux) - time;
1417 } else { /*DECRYPT*/
1418#ifndef _WIN32
1419 if (use_unhalted_cycles)
1420 time = read_cycles(params->core);
1421 else
1422#endif
1423 time = __rdtscp(&aux);
1424
9f95a23c
TL
1425 if (params->aes_key_size == AES_128_BYTES) {
1426 for (i = 0; i < num_iter; i++) {
f67539c2
TL
1427 uint8_t *pb = get_dst_buffer(index, p_buffer);
1428
9f95a23c
TL
1429 IMB_AES128_GCM_DEC(mb_mgr, &gdata_key,
1430 &gdata_ctx,
f67539c2
TL
1431 pb,
1432 pb,
9f95a23c 1433 size_aes, iv,
f67539c2 1434 aad, params->aad_size,
9f95a23c 1435 auth_tag, sizeof(auth_tag));
f67539c2 1436 index = get_next_index(index);
9f95a23c
TL
1437 }
1438 } else if (params->aes_key_size == AES_192_BYTES) {
1439 for (i = 0; i < num_iter; i++) {
f67539c2
TL
1440 uint8_t *pb = get_dst_buffer(index, p_buffer);
1441
9f95a23c
TL
1442 IMB_AES192_GCM_DEC(mb_mgr, &gdata_key,
1443 &gdata_ctx,
f67539c2
TL
1444 pb,
1445 pb,
9f95a23c 1446 size_aes, iv,
f67539c2 1447 aad, params->aad_size,
9f95a23c 1448 auth_tag, sizeof(auth_tag));
f67539c2 1449 index = get_next_index(index);
9f95a23c
TL
1450 }
1451 } else { /* 256 */
1452 for (i = 0; i < num_iter; i++) {
f67539c2
TL
1453 uint8_t *pb = get_dst_buffer(index, p_buffer);
1454
9f95a23c
TL
1455 IMB_AES256_GCM_DEC(mb_mgr, &gdata_key,
1456 &gdata_ctx,
f67539c2
TL
1457 pb,
1458 pb,
9f95a23c 1459 size_aes, iv,
f67539c2 1460 aad, params->aad_size,
9f95a23c 1461 auth_tag, sizeof(auth_tag));
f67539c2 1462 index = get_next_index(index);
9f95a23c 1463 }
11fdf7f2
TL
1464 }
1465#ifndef _WIN32
1466 if (use_unhalted_cycles)
1467 time = (read_cycles(params->core) -
1468 rd_cycles_cost) - time;
1469 else
1470#endif
1471 time = __rdtscp(&aux) - time;
1472 }
1473
1474 free(key);
f67539c2 1475 free(aad);
11fdf7f2
TL
1476 return time / num_iter;
1477}
1478
11fdf7f2 1479/* Computes mean of set of times after dropping bottom and top quarters */
f67539c2
TL
1480static uint64_t
1481mean_median(uint64_t *array, uint32_t size,
1482 uint8_t *p_buffer, uint128_t *p_keys)
11fdf7f2 1483{
f67539c2 1484 const uint32_t quarter = size / 4;
11fdf7f2
TL
1485 uint32_t i;
1486 uint64_t sum;
1487
1488 /* these are single threaded runs, so we skip
1489 * the hardware thread related skew clipping
1490 * thus skipping "ignore first and last eighth"
1491 */
1492
1493 /* ignore lowest and highest quarter */
1494 qsort(array, size, sizeof(uint64_t), compare_uint64_t);
1495
1496 /* dropping the bottom and top quarters
1497 * after sorting to remove noise/variations
1498 */
1499 array += quarter;
1500 size -= quarter * 2;
1501
1502
1503 if ((size == 0) || (size & 0x80000000)) {
f67539c2
TL
1504 fprintf(stderr, "Not enough data points!\n");
1505 free_mem(&p_buffer, &p_keys);
11fdf7f2
TL
1506 exit(EXIT_FAILURE);
1507 }
1508 sum = 0;
1509 for (i = 0; i < size; i++)
1510 sum += array[i];
1511
1512 sum = (sum + size / 2) / size;
1513 return sum;
1514}
1515
1516/* Runs test for each buffer size and stores averaged execution time */
1517static void
1518process_variant(MB_MGR *mgr, const uint32_t arch, struct params_s *params,
f67539c2
TL
1519 struct variant_s *variant_ptr, const uint32_t run,
1520 uint8_t *p_buffer, uint128_t *p_keys)
11fdf7f2
TL
1521{
1522 const uint32_t sizes = params->num_sizes;
1523 uint64_t *times = &variant_ptr->avg_times[run];
1524 uint32_t sz;
1525
1526 for (sz = 0; sz < sizes; sz++) {
f67539c2
TL
1527 const uint32_t size_aes = job_sizes[RANGE_MIN] +
1528 (sz * job_sizes[RANGE_STEP]);
1529 uint32_t num_iter;
1530
1531 params->aad_size = 0;
1532 if (params->cipher_mode == TEST_GCM)
1533 params->aad_size = gcm_aad_size;
1534
1535 if (params->cipher_mode == TEST_CCM)
1536 params->aad_size = ccm_aad_size;
1537
1538 /*
1539 * If job size == 0, check AAD size
1540 * (only allowed for GCM/CCM)
1541 */
1542 if (size_aes == 0 && params->aad_size != 0)
1543 num_iter = (iter_scale >= (uint32_t)params->aad_size) ?
1544 (iter_scale / (uint32_t)params->aad_size) :
1545 1;
1546 else if (size_aes != 0)
1547 num_iter = (iter_scale >= size_aes) ?
1548 (iter_scale / size_aes) : 1;
1549 else
1550 num_iter = iter_scale;
11fdf7f2
TL
1551
1552 params->size_aes = size_aes;
f67539c2
TL
1553 if (params->cipher_mode == TEST_GCM && (!use_gcm_job_api)) {
1554 if (job_iter == 0)
1555 *times = do_test_gcm(params, 2 * num_iter, mgr,
1556 p_buffer, p_keys);
1557 else
1558 *times = do_test_gcm(params, job_iter, mgr,
1559 p_buffer, p_keys);
1560 } else {
1561 if (job_iter == 0)
1562 *times = do_test(mgr, params, num_iter,
1563 p_buffer, p_keys);
1564 else
1565 *times = do_test(mgr, params, job_iter,
1566 p_buffer, p_keys);
1567 }
11fdf7f2
TL
1568 times += NUM_RUNS;
1569 }
1570
1571 variant_ptr->params = *params;
1572 variant_ptr->arch = arch;
1573}
1574
1575/* Sets cipher mode, hash algorithm */
1576static void
1577do_variants(MB_MGR *mgr, const uint32_t arch, struct params_s *params,
1578 const uint32_t run, struct variant_s **variant_ptr,
f67539c2
TL
1579 uint32_t *variant, uint8_t *p_buffer, uint128_t *p_keys,
1580 const int print_info)
11fdf7f2
TL
1581{
1582 uint32_t hash_alg;
1583 uint32_t h_start = TEST_SHA1;
1584 uint32_t h_end = TEST_NULL_HASH;
1585 uint32_t c_mode;
1586 uint32_t c_start = TEST_CBC;
1587 uint32_t c_end = TEST_NULL_CIPHER;
1588
1589 switch (params->test_type) {
1590 case TTYPE_AES_DOCSIS:
1591 h_start = TEST_NULL_HASH;
1592 c_start = TEST_AESDOCSIS;
1593 c_end = TEST_DESDOCSIS4;
1594 break;
1595 case TTYPE_AES_GCM:
1596 h_start = TEST_HASH_GCM;
1597 h_end = TEST_HASH_GCM;
1598 c_start = TEST_GCM;
1599 c_end = TEST_GCM;
1600 break;
1601 case TTYPE_AES_CCM:
1602 h_start = TEST_HASH_CCM;
1603 h_end = TEST_HASH_CCM;
1604 c_start = TEST_CCM;
1605 c_end = TEST_CCM;
1606 break;
1607 case TTYPE_AES_DES:
1608 h_start = TEST_NULL_HASH;
1609 h_end = TEST_NULL_HASH;
1610 c_start = TEST_DES;
1611 c_end = TEST_DES;
1612 break;
1613 case TTYPE_AES_3DES:
1614 h_start = TEST_NULL_HASH;
1615 h_end = TEST_NULL_HASH;
1616 c_start = TEST_3DES;
1617 c_end = TEST_3DES;
1618 break;
f67539c2
TL
1619 case TTYPE_PON:
1620 h_start = TEST_PON_CRC_BIP;
1621 h_end = TEST_PON_CRC_BIP;
1622 c_start = TEST_PON_CNTR;
1623 c_end = TEST_PON_NO_CNTR;
1624 break;
1625 case TTYPE_CUSTOM:
1626 h_start = params->hash_alg;
1627 h_end = params->hash_alg;
1628 c_start = params->cipher_mode;
1629 c_end = params->cipher_mode;
1630 break;
11fdf7f2
TL
1631 default:
1632 break;
1633 }
1634
1635 for (c_mode = c_start; c_mode <= c_end; c_mode++) {
1636 params->cipher_mode = (enum test_cipher_mode_e) c_mode;
1637 for (hash_alg = h_start; hash_alg <= h_end; hash_alg++) {
1638 params->hash_alg = (enum test_hash_alg_e) hash_alg;
f67539c2
TL
1639 process_variant(mgr, arch, params, *variant_ptr, run,
1640 p_buffer, p_keys);
1641 /* update and print progress bar */
1642 if (print_info)
1643 prog_bar_update(*variant);
11fdf7f2
TL
1644 (*variant)++;
1645 (*variant_ptr)++;
1646 }
1647 }
1648}
1649
1650/* Sets cipher direction and key size */
1651static void
1652run_dir_test(MB_MGR *mgr, const uint32_t arch, struct params_s *params,
1653 const uint32_t run, struct variant_s **variant_ptr,
f67539c2
TL
1654 uint32_t *variant, uint8_t *p_buffer, uint128_t *p_keys,
1655 const int print_info)
11fdf7f2
TL
1656{
1657 uint32_t dir;
1658 uint32_t k; /* Key size */
1659 uint32_t limit = AES_256_BYTES; /* Key size value limit */
1660
1661 if (params->test_type == TTYPE_AES_DOCSIS ||
1662 params->test_type == TTYPE_AES_DES ||
1663 params->test_type == TTYPE_AES_3DES ||
f67539c2 1664 params->test_type == TTYPE_PON ||
11fdf7f2
TL
1665 params->test_type == TTYPE_AES_CCM)
1666 limit = AES_128_BYTES;
1667
9f95a23c
TL
1668 switch (arch) {
1669 case 0:
1670 init_mb_mgr_sse(mgr);
1671 break;
1672 case 1:
1673 init_mb_mgr_avx(mgr);
1674 break;
1675 case 2:
1676 init_mb_mgr_avx2(mgr);
1677 break;
1678 default:
1679 case 3:
1680 init_mb_mgr_avx512(mgr);
1681 break;
1682 }
11fdf7f2 1683
f67539c2
TL
1684 if (params->test_type == TTYPE_CUSTOM) {
1685 params->cipher_dir = custom_job_params.cipher_dir;
1686 params->aes_key_size = custom_job_params.aes_key_size;
1687 params->cipher_mode = custom_job_params.cipher_mode;
1688 params->hash_alg = custom_job_params.hash_alg;
1689 do_variants(mgr, arch, params, run, variant_ptr,
1690 variant, p_buffer, p_keys, print_info);
1691 return;
1692 }
1693
11fdf7f2
TL
1694 for (dir = ENCRYPT; dir <= DECRYPT; dir++) {
1695 params->cipher_dir = (JOB_CIPHER_DIRECTION) dir;
1696 for (k = AES_128_BYTES; k <= limit; k += 8) {
1697 params->aes_key_size = k;
1698 do_variants(mgr, arch, params, run, variant_ptr,
f67539c2 1699 variant, p_buffer, p_keys, print_info);
11fdf7f2
TL
1700 }
1701 }
1702}
1703
1704/* Generates output containing averaged times for each test variant */
f67539c2
TL
1705static void
1706print_times(struct variant_s *variant_list, struct params_s *params,
1707 const uint32_t total_variants, uint8_t *p_buffer, uint128_t *p_keys)
11fdf7f2
TL
1708{
1709 const uint32_t sizes = params->num_sizes;
1710 uint32_t col;
1711 uint32_t sz;
1712
1713 /* Temporary variables */
1714 struct params_s par;
1715 uint8_t c_mode;
1716 uint8_t c_dir;
1717 uint8_t h_alg;
1718 const char *func_names[4] = {
1719 "SSE", "AVX", "AVX2", "AVX512"
1720 };
f67539c2
TL
1721 const char *c_mode_names[TEST_NUM_CIPHER_TESTS - 1] = {
1722 "CBC", "CNTR", "CNTR+8", "CNTR_BITLEN", "CNTR_BITLEN4", "ECB",
1723 "NULL_CIPHER", "DOCAES", "DOCAES+8", "DOCDES", "DOCDES+4",
1724 "GCM", "CCM", "DES", "3DES", "PON", "PON_NO_CTR"
11fdf7f2
TL
1725 };
1726 const char *c_dir_names[2] = {
1727 "ENCRYPT", "DECRYPT"
1728 };
f67539c2 1729 const char *h_alg_names[TEST_NUM_HASH_TESTS - 1] = {
11fdf7f2 1730 "SHA1", "SHA_224", "SHA_256", "SHA_384", "SHA_512", "XCBC",
f67539c2
TL
1731 "MD5", "CMAC", "CMAC_BITLEN", "NULL_HASH", "GCM", "CUSTOM",
1732 "CCM", "BIP-CRC32"
11fdf7f2
TL
1733 };
1734 printf("ARCH");
1735 for (col = 0; col < total_variants; col++)
1736 printf("\t%s", func_names[variant_list[col].arch]);
1737 printf("\n");
1738 printf("CIPHER");
1739 for (col = 0; col < total_variants; col++) {
1740 par = variant_list[col].params;
f67539c2 1741 c_mode = par.cipher_mode - TEST_CBC;
11fdf7f2
TL
1742 printf("\t%s", c_mode_names[c_mode]);
1743 }
1744 printf("\n");
1745 printf("DIR");
1746 for (col = 0; col < total_variants; col++) {
1747 par = variant_list[col].params;
1748 c_dir = par.cipher_dir - ENCRYPT;
1749 printf("\t%s", c_dir_names[c_dir]);
1750 }
1751 printf("\n");
1752 printf("HASH_ALG");
1753 for (col = 0; col < total_variants; col++) {
1754 par = variant_list[col].params;
f67539c2 1755 h_alg = par.hash_alg - TEST_SHA1;
11fdf7f2
TL
1756 printf("\t%s", h_alg_names[h_alg]);
1757 }
1758 printf("\n");
1759 printf("KEY_SIZE");
1760 for (col = 0; col < total_variants; col++) {
1761 par = variant_list[col].params;
1762 printf("\tAES-%u", par.aes_key_size * 8);
1763 }
1764 printf("\n");
1765 for (sz = 0; sz < sizes; sz++) {
f67539c2
TL
1766 printf("%d", job_sizes[RANGE_MIN] +
1767 (sz * job_sizes[RANGE_STEP]));
11fdf7f2
TL
1768 for (col = 0; col < total_variants; col++) {
1769 uint64_t *time_ptr =
1770 &variant_list[col].avg_times[sz * NUM_RUNS];
1771 const unsigned long long val =
f67539c2
TL
1772 mean_median(time_ptr, NUM_RUNS,
1773 p_buffer, p_keys);
11fdf7f2
TL
1774
1775 printf("\t%llu", val);
1776 }
1777 printf("\n");
1778 }
1779}
1780
1781/* Prepares data structure for test variants storage, sets test configuration */
1782#ifdef _WIN32
1783static void
1784#else
1785static void *
1786#endif
1787run_tests(void *arg)
1788{
1789 uint32_t i;
1790 struct thread_info *info = (struct thread_info *)arg;
1791 MB_MGR *p_mgr = NULL;
1792 struct params_s params;
f67539c2 1793 uint32_t num_variants[NUM_TTYPES] = {0};
11fdf7f2
TL
1794 uint32_t type, at_size, run, arch;
1795 uint32_t variants_per_arch, max_arch;
1796 uint32_t variant;
1797 uint32_t total_variants = 0;
1798 struct variant_s *variant_ptr = NULL;
1799 struct variant_s *variant_list = NULL;
f67539c2
TL
1800 const uint32_t min_size = job_sizes[RANGE_MIN];
1801 const uint32_t max_size = job_sizes[RANGE_MAX];
1802 const uint32_t step_size = job_sizes[RANGE_STEP];
1803 uint8_t *buf = NULL;
1804 uint128_t *keys = NULL;
11fdf7f2 1805
9f95a23c 1806 p_mgr = info->p_mgr;
f67539c2
TL
1807
1808 params.num_sizes = ((max_size - min_size) / step_size) + 1;
1809
11fdf7f2
TL
1810 params.core = (uint32_t)info->core;
1811
1812 /* if cores selected then set affinity */
1813 if (core_mask)
1814 if (set_affinity(info->core) != 0) {
1815 fprintf(stderr, "Failed to set cpu "
1816 "affinity on core %d\n", info->core);
1817 goto exit_failure;
1818 }
1819
1820 /* If unhalted cycles selected and this is
1821 the primary thread then start counter */
1822 if (use_unhalted_cycles && info->print_info) {
1823 int ret;
1824
1825 ret = start_cycles_ctr(params.core);
1826 if (ret != 0) {
1827 fprintf(stderr, "Failed to start cycles "
1828 "counter on core %u\n", params.core);
1829 goto exit_failure;
1830 }
1831 /* Get average cost of reading counter */
1832 ret = set_avg_unhalted_cycle_cost(params.core, &rd_cycles_cost);
1833 if (ret != 0 || rd_cycles_cost == 0) {
1834 fprintf(stderr, "Error calculating unhalted "
1835 "cycles read overhead!\n");
1836 goto exit_failure;
1837 } else
1838 fprintf(stderr, "Started counting unhalted cycles on "
1839 "core %d\nUnhalted cycles read cost = %lu "
1840 "cycles\n", params.core,
1841 (unsigned long)rd_cycles_cost);
1842 }
1843
f67539c2
TL
1844 init_mem(&buf, &keys);
1845
1846 for (type = TTYPE_AES_HMAC; type < NUM_TTYPES; type++) {
11fdf7f2
TL
1847 if (test_types[type] == 0)
1848 continue;
1849
1850 switch (type) {
1851 default:
1852 case TTYPE_AES_HMAC:
1853 variants_per_arch = VARIANTS_PER_ARCH_AES;
1854 max_arch = NUM_ARCHS;
1855 break;
1856 case TTYPE_AES_DOCSIS:
1857 variants_per_arch = VARIANTS_PER_ARCH_DOCSIS;
1858 max_arch = NUM_ARCHS;
1859 break;
1860 case TTYPE_AES_GCM:
1861 variants_per_arch = VARIANTS_PER_ARCH_GCM;
9f95a23c 1862 max_arch = NUM_ARCHS;
11fdf7f2
TL
1863 break;
1864 case TTYPE_AES_CCM:
1865 variants_per_arch = VARIANTS_PER_ARCH_CCM;
1866 max_arch = NUM_ARCHS;
1867 break;
1868 case TTYPE_AES_DES:
1869 variants_per_arch = VARIANTS_PER_ARCH_DES;
1870 max_arch = NUM_ARCHS;
1871 break;
1872 case TTYPE_AES_3DES:
1873 variants_per_arch = VARIANTS_PER_ARCH_3DES;
1874 max_arch = NUM_ARCHS;
1875 break;
f67539c2
TL
1876 case TTYPE_PON:
1877 variants_per_arch = VARIANTS_PER_ARCH_PON;
1878 max_arch = NUM_ARCHS;
1879 break;
1880 case TTYPE_CUSTOM:
1881 variants_per_arch = 1;
1882 max_arch = NUM_ARCHS;
1883 break;
11fdf7f2
TL
1884 }
1885
1886 /* Calculating number of all variants */
1887 for (arch = 0; arch < max_arch; arch++) {
1888 if (archs[arch] == 0)
1889 continue;
1890 num_variants[type] += variants_per_arch;
1891 }
1892 total_variants += num_variants[type];
1893 }
1894
f67539c2
TL
1895 if (total_variants == 0) {
1896 fprintf(stderr, "No tests to be run\n");
1897 goto exit;
1898 }
1899
1900 if (info->print_info && !silent_progress_bar)
1901 fprintf(stderr, "Total number of combinations (algos, "
1902 "key sizes, cipher directions) to test = %u\n",
1903 total_variants);
1904
11fdf7f2
TL
1905 variant_list = (struct variant_s *)
1906 malloc(total_variants * sizeof(struct variant_s));
1907 if (variant_list == NULL) {
1908 fprintf(stderr, "Cannot allocate memory\n");
1909 goto exit_failure;
1910 }
1911
1912 at_size = NUM_RUNS * params.num_sizes * sizeof(uint64_t);
1913 for (variant = 0, variant_ptr = variant_list;
1914 variant < total_variants;
1915 variant++, variant_ptr++) {
1916 variant_ptr->avg_times = (uint64_t *) malloc(at_size);
1917 if (!variant_ptr->avg_times) {
1918 fprintf(stderr, "Cannot allocate memory\n");
1919 goto exit_failure;
1920 }
1921 }
f67539c2 1922
11fdf7f2 1923 for (run = 0; run < NUM_RUNS; run++) {
f67539c2
TL
1924 if (info->print_info)
1925 fprintf(stderr, "\nStarting run %d of %d%c",
1926 run+1, NUM_RUNS,
1927 silent_progress_bar ? '\r' : '\n' );
11fdf7f2
TL
1928
1929 variant = 0;
1930 variant_ptr = variant_list;
1931
9f95a23c
TL
1932 if (iter_scale == ITER_SCALE_SMOKE && run != 0)
1933 continue;
1934
f67539c2
TL
1935 if (info->print_info)
1936 prog_bar_init(total_variants);
1937
1938 for (type = TTYPE_AES_HMAC; type < NUM_TTYPES; type++) {
11fdf7f2
TL
1939 if (test_types[type] == 0)
1940 continue;
1941
9f95a23c 1942 max_arch = NUM_ARCHS;
11fdf7f2
TL
1943
1944 params.num_variants = num_variants[type];
1945 params.test_type = type;
1946 /* Performing tests for each selected architecture */
1947 for (arch = 0; arch < max_arch; arch++) {
1948 if (archs[arch] == 0)
1949 continue;
1950 run_dir_test(p_mgr, arch, &params, run,
f67539c2
TL
1951 &variant_ptr, &variant, buf,
1952 keys, info->print_info);
11fdf7f2
TL
1953 }
1954 } /* end for type */
f67539c2
TL
1955 if (info->print_info)
1956 prog_bar_fini();
1957
11fdf7f2 1958 } /* end for run */
f67539c2
TL
1959 if (info->print_info == 1 && iter_scale != ITER_SCALE_SMOKE) {
1960 fprintf(stderr, "\n");
1961 print_times(variant_list, &params, total_variants, buf, keys);
1962 }
11fdf7f2 1963
f67539c2 1964exit:
11fdf7f2
TL
1965 if (variant_list != NULL) {
1966 /* Freeing variants list */
1967 for (i = 0; i < total_variants; i++)
1968 free(variant_list[i].avg_times);
1969 free(variant_list);
1970 }
f67539c2 1971 free_mem(&buf, &keys);
11fdf7f2
TL
1972 free_mb_mgr(p_mgr);
1973#ifndef _WIN32
1974 return NULL;
1975
1976#else
1977 return;
1978#endif
1979exit_failure:
1980 if (variant_list != NULL)
1981 free(variant_list);
f67539c2 1982 free_mem(&buf, &keys);
11fdf7f2
TL
1983 free_mb_mgr(p_mgr);
1984 exit(EXIT_FAILURE);
1985}
1986
1987static void usage(void)
1988{
1989 fprintf(stderr, "Usage: ipsec_perf [args], "
1990 "where args are zero or more\n"
1991 "-h: print this message\n"
1992 "-c: Use cold cache, it uses warm as default\n"
1993 "-w: Use warm cache\n"
f67539c2
TL
1994 "--arch: run only tests on specified architecture (SSE/AVX/AVX2/AVX512)\n"
1995 "--cipher-algo: Select cipher algorithm to run on the custom test\n"
1996 "--cipher-dir: Select cipher direction to run on the custom test "
1997 "(encrypt/decrypt) (default = encrypt)\n"
1998 "--hash-algo: Select hash algorithm to run on the custom test\n"
1999 "--aead-algo: Select AEAD algorithm to run on the custom test\n"
11fdf7f2
TL
2000 "--no-avx512: Don't do AVX512\n"
2001 "--no-avx2: Don't do AVX2\n"
2002 "--no-avx: Don't do AVX\n"
2003 "--no-sse: Don't do SSE\n"
2004 "-o val: Use <val> for the SHA size increment, default is 24\n"
2005 "--shani-on: use SHA extensions, default: auto-detect\n"
2006 "--shani-off: don't use SHA extensions\n"
2007 "--no-gcm: do not run GCM perf tests\n"
2008 "--no-aes: do not run standard AES + HMAC perf tests\n"
2009 "--no-docsis: do not run DOCSIS cipher perf tests\n"
2010 "--no-ccm: do not run CCM cipher perf tests\n"
2011 "--no-des: do not run DES cipher perf tests\n"
2012 "--no-3des: do not run 3DES cipher perf tests\n"
f67539c2 2013 "--no-pon: do not run PON cipher perf tests\n"
11fdf7f2
TL
2014 "--gcm-job-api: use JOB API for GCM perf tests"
2015 " (raw GCM API is default)\n"
2016 "--threads num: <num> for the number of threads to run"
2017 " Max: %d\n"
2018 "--cores mask: <mask> CPU's to run threads\n"
2019 "--unhalted-cycles: measure using unhalted cycles (requires root).\n"
9f95a23c 2020 " Note: RDTSC is used by default.\n"
f67539c2
TL
2021 "--quick: reduces number of test iterations by x10\n"
2022 " (less precise but quicker)\n"
2023 "--smoke: very quick, unprecise and without print out\n"
2024 " (for validation only)\n"
2025 "--job-size: size of the cipher & MAC job in bytes. It can be:\n"
2026 " - single value: test single size\n"
2027 " - range: test multiple sizes with following format"
2028 " min:step:max (e.g. 16:16:256)\n"
2029 " (-o still applies for MAC)\n"
2030 "--aad-size: size of AAD for AEAD algorithms\n"
2031 "--job-iter: number of tests iterations for each job size\n"
2032 "--no-progress-bar: Don't display progress bar\n",
11fdf7f2
TL
2033 MAX_NUM_THREADS + 1);
2034}
2035
f67539c2
TL
2036static int
2037get_next_num_arg(const char * const *argv, const int index, const int argc,
2038 void *dst, const size_t dst_size)
2039{
2040 char *endptr = NULL;
2041 uint64_t val;
2042
2043 if (dst == NULL || argv == NULL || index < 0 || argc < 0) {
2044 fprintf(stderr, "%s() internal error!\n", __func__);
2045 exit(EXIT_FAILURE);
2046 }
2047
2048 if (index >= (argc - 1)) {
2049 fprintf(stderr, "'%s' requires an argument!\n", argv[index]);
2050 exit(EXIT_FAILURE);
2051 }
2052
2053#ifdef _WIN32
2054 val = _strtoui64(argv[index + 1], &endptr, 0);
2055#else
2056 val = strtoull(argv[index + 1], &endptr, 0);
2057#endif
2058 if (endptr == argv[index + 1] || (endptr != NULL && *endptr != '\0')) {
2059 fprintf(stderr, "Error converting '%s' as value for '%s'!\n",
2060 argv[index + 1], argv[index]);
2061 exit(EXIT_FAILURE);
2062 }
2063
2064 switch (dst_size) {
2065 case (sizeof(uint8_t)):
2066 *((uint8_t *)dst) = (uint8_t) val;
2067 break;
2068 case (sizeof(uint16_t)):
2069 *((uint16_t *)dst) = (uint16_t) val;
2070 break;
2071 case (sizeof(uint32_t)):
2072 *((uint32_t *)dst) = (uint32_t) val;
2073 break;
2074 case (sizeof(uint64_t)):
2075 *((uint64_t *)dst) = val;
2076 break;
2077 default:
2078 fprintf(stderr, "%s() invalid dst_size %u!\n",
2079 __func__, (unsigned) dst_size);
2080 exit(EXIT_FAILURE);
2081 break;
2082 }
2083
2084 return index + 1;
2085}
2086
2087static int
2088detect_arch(unsigned int arch_support[NUM_ARCHS])
2089{
2090 const uint64_t detect_sse =
2091 IMB_FEATURE_SSE4_2 | IMB_FEATURE_CMOV | IMB_FEATURE_AESNI;
2092 const uint64_t detect_avx =
2093 IMB_FEATURE_AVX | IMB_FEATURE_CMOV | IMB_FEATURE_AESNI;
2094 const uint64_t detect_avx2 = IMB_FEATURE_AVX2 | detect_avx;
2095 const uint64_t detect_avx512 = IMB_FEATURE_AVX512_SKX | detect_avx2;
2096 MB_MGR *p_mgr = NULL;
2097 enum arch_type_e arch_id;
2098
2099 if (arch_support == NULL) {
2100 fprintf(stderr, "Array not passed correctly\n");
2101 return -1;
2102 }
2103
2104 for (arch_id = ARCH_SSE; arch_id < NUM_ARCHS; arch_id++)
2105 arch_support[arch_id] = 1;
2106
2107 p_mgr = alloc_mb_mgr(0);
2108 if (p_mgr == NULL) {
2109 fprintf(stderr, "Architecture detect error!\n");
2110 return -1;
2111 }
2112
2113 if ((p_mgr->features & detect_avx512) != detect_avx512)
2114 arch_support[ARCH_AVX512] = 0;
2115
2116 if ((p_mgr->features & detect_avx2) != detect_avx2)
2117 arch_support[ARCH_AVX2] = 0;
2118
2119 if ((p_mgr->features & detect_avx) != detect_avx)
2120 arch_support[ARCH_AVX] = 0;
2121
2122 if ((p_mgr->features & detect_sse) != detect_sse)
2123 arch_support[ARCH_SSE] = 0;
2124
2125 free_mb_mgr(p_mgr);
2126
2127 return 0;
2128}
2129
2130/*
2131 * Check string argument is supported and if it is, return values associated
2132 * with it.
2133 */
2134static const union params *
2135check_string_arg(const char *param, const char *arg,
2136 const struct str_value_mapping *map,
2137 const unsigned int num_avail_opts)
2138{
2139 unsigned int i;
2140
2141 if (arg == NULL) {
2142 fprintf(stderr, "%s requires an argument\n", param);
2143 goto exit;
2144 }
2145
2146 for (i = 0; i < num_avail_opts; i++)
2147 if (strcmp(arg, map[i].name) == 0)
2148 return &(map[i].values);
2149
2150 /* Argument is not listed in the available options */
2151 fprintf(stderr, "Invalid argument for %s\n", param);
2152exit:
2153 fprintf(stderr, "Accepted arguments: ");
2154 for (i = 0; i < num_avail_opts; i++)
2155 fprintf(stderr, "%s ", map[i].name);
2156 fprintf(stderr, "\n");
2157
2158 return NULL;
2159}
2160
2161static int
2162parse_range(const char * const *argv, const int index, const int argc,
2163 uint32_t range_values[NUM_RANGE])
2164{
2165 char *token;
2166 uint32_t number;
2167 unsigned int i;
2168
2169
2170 if (range_values == NULL || argv == NULL || index < 0 || argc < 0) {
2171 fprintf(stderr, "%s() internal error!\n", __func__);
2172 exit(EXIT_FAILURE);
2173 }
2174
2175 if (index >= (argc - 1)) {
2176 fprintf(stderr, "'%s' requires an argument!\n", argv[index]);
2177 exit(EXIT_FAILURE);
2178 }
2179
2180 char *copy_arg = strdup(argv[index + 1]);
2181
2182 if (copy_arg == NULL) {
2183 fprintf(stderr, "%s() internal error!\n", __func__);
2184 exit(EXIT_FAILURE);
2185 }
2186
2187 errno = 0;
2188 token = strtok(copy_arg, ":");
2189
2190 /* Try parsing range (minimum, step and maximum values) */
2191 for (i = 0; i < NUM_RANGE; i++) {
2192 if (token == NULL)
2193 goto no_range;
2194
2195 number = strtoul(token, NULL, 10);
2196
2197 if (errno != 0)
2198 goto no_range;
2199
2200 range_values[i] = number;
2201 token = strtok(NULL, ":");
2202 }
2203
2204 if (token != NULL)
2205 goto no_range;
2206
2207 if (range_values[RANGE_MAX] < range_values[RANGE_MIN]) {
2208 fprintf(stderr, "Maximum value of range cannot be lower "
2209 "than minimum value\n");
2210 exit(EXIT_FAILURE);
2211 }
2212
2213 if (range_values[RANGE_STEP] == 0) {
2214 fprintf(stderr, "Step value in range cannot be 0\n");
2215 exit(EXIT_FAILURE);
2216 }
2217
2218 goto end_range;
2219no_range:
2220 /* Try parsing as single value */
2221 get_next_num_arg(argv, index, argc, &job_sizes[RANGE_MIN],
2222 sizeof(job_sizes[RANGE_MIN]));
2223
2224 job_sizes[RANGE_MAX] = job_sizes[RANGE_MIN];
2225
2226end_range:
2227 free(copy_arg);
2228 return (index + 1);
2229
2230}
2231
11fdf7f2
TL
2232int main(int argc, char *argv[])
2233{
f67539c2
TL
2234 uint32_t num_t = 0;
2235 int i, core = 0;
11fdf7f2 2236 struct thread_info *thread_info_p = t_info;
f67539c2
TL
2237 unsigned int arch_id;
2238 unsigned int arch_support[NUM_ARCHS];
2239 const union params *values;
2240 unsigned int cipher_algo_set = 0;
2241 unsigned int hash_algo_set = 0;
2242 unsigned int aead_algo_set = 0;
2243 unsigned int cipher_dir_set = 0;
11fdf7f2
TL
2244#ifdef _WIN32
2245 HANDLE threads[MAX_NUM_THREADS];
2246#else
2247 pthread_t tids[MAX_NUM_THREADS];
2248#endif
2249
2250 for (i = 1; i < argc; i++)
2251 if (strcmp(argv[i], "-h") == 0) {
2252 usage();
2253 return EXIT_SUCCESS;
2254 } else if (strcmp(argv[i], "-c") == 0) {
2255 cache_type = COLD;
2256 fprintf(stderr, "Cold cache, ");
2257 } else if (strcmp(argv[i], "-w") == 0) {
2258 cache_type = WARM;
2259 fprintf(stderr, "Warm cache, ");
2260 } else if (strcmp(argv[i], "--no-avx512") == 0) {
2261 archs[ARCH_AVX512] = 0;
2262 } else if (strcmp(argv[i], "--no-avx2") == 0) {
2263 archs[ARCH_AVX2] = 0;
2264 } else if (strcmp(argv[i], "--no-avx") == 0) {
2265 archs[ARCH_AVX] = 0;
2266 } else if (strcmp(argv[i], "--no-sse") == 0) {
2267 archs[ARCH_SSE] = 0;
2268 } else if (strcmp(argv[i], "--shani-on") == 0) {
2269 flags &= (~IMB_FLAG_SHANI_OFF);
2270 } else if (strcmp(argv[i], "--shani-off") == 0) {
2271 flags |= IMB_FLAG_SHANI_OFF;
2272 } else if (strcmp(argv[i], "--no-gcm") == 0) {
2273 test_types[TTYPE_AES_GCM] = 0;
2274 } else if (strcmp(argv[i], "--no-aes") == 0) {
2275 test_types[TTYPE_AES_HMAC] = 0;
2276 } else if (strcmp(argv[i], "--no-docsis") == 0) {
2277 test_types[TTYPE_AES_DOCSIS] = 0;
2278 } else if (strcmp(argv[i], "--no-ccm") == 0) {
2279 test_types[TTYPE_AES_CCM] = 0;
2280 } else if (strcmp(argv[i], "--no-des") == 0) {
2281 test_types[TTYPE_AES_DES] = 0;
2282 } else if (strcmp(argv[i], "--no-3des") == 0) {
2283 test_types[TTYPE_AES_3DES] = 0;
f67539c2
TL
2284 } else if (strcmp(argv[i], "--no-pon") == 0) {
2285 test_types[TTYPE_PON] = 0;
11fdf7f2
TL
2286 } else if (strcmp(argv[i], "--gcm-job-api") == 0) {
2287 use_gcm_job_api = 1;
9f95a23c
TL
2288 } else if (strcmp(argv[i], "--quick") == 0) {
2289 iter_scale = ITER_SCALE_SHORT;
2290 } else if (strcmp(argv[i], "--smoke") == 0) {
2291 iter_scale = ITER_SCALE_SMOKE;
f67539c2
TL
2292 } else if (strcmp(argv[i], "--arch") == 0) {
2293 values = check_string_arg(argv[i], argv[i+1],
2294 arch_str_map,
2295 DIM(arch_str_map));
2296 if (values == NULL)
2297 return EXIT_FAILURE;
2298
2299 /*
2300 * Disable all the other architectures
2301 * and enable only the specified
2302 */
2303 memset(archs, 0, sizeof(archs));
2304 archs[values->arch_type] = 1;
2305 i++;
2306 } else if (strcmp(argv[i], "--cipher-algo") == 0) {
2307 values = check_string_arg(argv[i], argv[i+1],
2308 cipher_algo_str_map,
2309 DIM(cipher_algo_str_map));
2310 if (values == NULL)
2311 return EXIT_FAILURE;
2312
2313 custom_job_params.cipher_mode =
2314 values->job_params.cipher_mode;
2315 custom_job_params.aes_key_size =
2316 values->job_params.aes_key_size;
2317 test_types[TTYPE_CUSTOM] = 1;
2318 cipher_algo_set = 1;
2319 i++;
2320 } else if (strcmp(argv[i], "--cipher-dir") == 0) {
2321 values = check_string_arg(argv[i], argv[i+1],
2322 cipher_dir_str_map,
2323 DIM(cipher_dir_str_map));
2324 if (values == NULL)
2325 return EXIT_FAILURE;
2326
2327 custom_job_params.cipher_dir =
2328 values->job_params.cipher_dir;
2329 cipher_dir_set = 1;
2330 i++;
2331 } else if (strcmp(argv[i], "--hash-algo") == 0) {
2332 values = check_string_arg(argv[i], argv[i+1],
2333 hash_algo_str_map,
2334 DIM(hash_algo_str_map));
2335 if (values == NULL)
2336 return EXIT_FAILURE;
2337
2338 custom_job_params.hash_alg =
2339 values->job_params.hash_alg;
2340 test_types[TTYPE_CUSTOM] = 1;
2341 hash_algo_set = 1;
2342 i++;
2343 } else if (strcmp(argv[i], "--aead-algo") == 0) {
2344 values = check_string_arg(argv[i], argv[i+1],
2345 aead_algo_str_map,
2346 DIM(aead_algo_str_map));
2347 if (values == NULL)
2348 return EXIT_FAILURE;
2349
2350 custom_job_params.cipher_mode =
2351 values->job_params.cipher_mode;
2352 custom_job_params.aes_key_size =
2353 values->job_params.aes_key_size;
2354 custom_job_params.hash_alg =
2355 values->job_params.hash_alg;
2356 test_types[TTYPE_CUSTOM] = 1;
2357 aead_algo_set = 1;
11fdf7f2 2358 i++;
f67539c2
TL
2359 } else if (strcmp(argv[i], "-o") == 0) {
2360 i = get_next_num_arg((const char * const *)argv, i,
2361 argc, &sha_size_incr,
2362 sizeof(sha_size_incr));
2363 } else if (strcmp(argv[i], "--job-size") == 0) {
2364 /* Try parsing the argument as a range first */
2365 i = parse_range((const char * const *)argv, i, argc,
2366 job_sizes);
2367 if (job_sizes[RANGE_MAX] > JOB_SIZE_TOP) {
2368 fprintf(stderr,
2369 "Invalid job size %u (max %u)\n",
2370 (unsigned) job_sizes[RANGE_MAX],
2371 JOB_SIZE_TOP);
2372 return EXIT_FAILURE;
2373 }
2374 } else if (strcmp(argv[i], "--aad-size") == 0) {
2375 /* Get AAD size for both GCM and CCM */
2376 i = get_next_num_arg((const char * const *)argv, i,
2377 argc, &gcm_aad_size,
2378 sizeof(gcm_aad_size));
2379 if (gcm_aad_size > AAD_SIZE_MAX) {
2380 fprintf(stderr,
2381 "Invalid AAD size %u (max %u)!\n",
2382 (unsigned) gcm_aad_size,
2383 AAD_SIZE_MAX);
2384 return EXIT_FAILURE;
2385 }
2386 ccm_aad_size = gcm_aad_size;
2387 } else if (strcmp(argv[i], "--job-iter") == 0) {
2388 i = get_next_num_arg((const char * const *)argv, i,
2389 argc, &job_iter, sizeof(job_iter));
11fdf7f2 2390 } else if (strcmp(argv[i], "--threads") == 0) {
f67539c2
TL
2391 i = get_next_num_arg((const char * const *)argv, i,
2392 argc, &num_t, sizeof(num_t));
11fdf7f2
TL
2393 if (num_t > (MAX_NUM_THREADS + 1)) {
2394 fprintf(stderr, "Invalid number of threads!\n");
2395 return EXIT_FAILURE;
2396 }
2397 } else if (strcmp(argv[i], "--cores") == 0) {
f67539c2
TL
2398 i = get_next_num_arg((const char * const *)argv, i,
2399 argc, &core_mask,
2400 sizeof(core_mask));
11fdf7f2 2401 } else if (strcmp(argv[i], "--unhalted-cycles") == 0) {
11fdf7f2 2402 use_unhalted_cycles = 1;
f67539c2
TL
2403 } else if (strcmp(argv[i], "--no-progress-bar") == 0) {
2404 silent_progress_bar = 1;
11fdf7f2
TL
2405 } else {
2406 usage();
2407 return EXIT_FAILURE;
2408 }
2409
f67539c2
TL
2410 if (test_types[TTYPE_CUSTOM]) {
2411 /* Disable all other tests when custom test is selected */
2412 memset(test_types, 0, sizeof(test_types));
2413 test_types[TTYPE_CUSTOM] = 1;
2414 if (aead_algo_set && (cipher_algo_set || hash_algo_set)) {
2415 fprintf(stderr, "AEAD algorithm cannot be used "
2416 "combined with another cipher/hash "
2417 "algorithm\n");
2418 return EXIT_FAILURE;
2419 }
2420 }
2421
2422 if (cipher_algo_set == 0 && aead_algo_set == 0 && cipher_dir_set) {
2423 fprintf(stderr, "--cipher-dir can only be used with "
2424 "--cipher-algo or --aead-algo\n");
2425 return EXIT_FAILURE;
2426 }
2427
2428 if (test_types[TTYPE_AES_CCM] ||
2429 custom_job_params.cipher_mode == TEST_CCM) {
2430 if (ccm_aad_size > CCM_AAD_SIZE_MAX) {
2431 fprintf(stderr, "AAD cannot be higher than %u in CCM\n",
2432 CCM_AAD_SIZE_MAX);
2433 return EXIT_FAILURE;
2434 }
2435 }
2436
2437 if (job_sizes[RANGE_MIN] == 0) {
2438 if (test_types[TTYPE_AES_HMAC] ||
2439 test_types[TTYPE_AES_DOCSIS] ||
2440 test_types[TTYPE_AES_DES] ||
2441 test_types[TTYPE_AES_3DES] ||
2442 (test_types[TTYPE_CUSTOM] &&
2443 aead_algo_set == 0)) {
2444 fprintf(stderr, "Buffer size cannot be 0 unless only "
2445 "an AEAD algorithm is tested\n");
2446 return EXIT_FAILURE;
2447 }
2448 }
2449
11fdf7f2
TL
2450 /* Check num cores >= number of threads */
2451 if ((core_mask != 0 && num_t != 0) && (num_t > bitcount(core_mask))) {
2452 fprintf(stderr, "Insufficient number of cores in "
2453 "core mask (0x%lx) to run %d threads!\n",
2454 (unsigned long) core_mask, num_t);
2455 return EXIT_FAILURE;
2456 }
2457
2458 /* if cycles selected then init MSR module */
2459 if (use_unhalted_cycles) {
2460 if (core_mask == 0) {
2461 fprintf(stderr, "Must specify core mask "
2462 "when reading unhalted cycles!\n");
2463 return EXIT_FAILURE;
2464 }
2465
2466 if (init_msr_mod() != 0) {
2467 fprintf(stderr, "Error initializing MSR module!\n");
2468 return EXIT_FAILURE;
2469 }
2470 }
2471
f67539c2
TL
2472 if (detect_arch(arch_support) < 0)
2473 return EXIT_FAILURE;
2474
2475 /* disable tests depending on instruction sets supported */
2476 for (arch_id = 0; arch_id < NUM_ARCHS; arch_id++) {
2477 if (archs[arch_id] == 1 && arch_support[arch_id] == 0) {
2478 archs[arch_id] = 0;
2479 fprintf(stderr,
2480 "%s not supported. Disabling %s tests\n",
2481 arch_str_map[arch_id].name,
2482 arch_str_map[arch_id].name);
2483 }
2484 }
2485
11fdf7f2 2486 fprintf(stderr, "SHA size incr = %d\n", sha_size_incr);
f67539c2
TL
2487
2488 if (test_types[TTYPE_AES_GCM] ||
2489 (custom_job_params.cipher_mode == TEST_GCM))
2490 fprintf(stderr, "GCM AAD = %"PRIu64"\n", gcm_aad_size);
2491
2492 if (test_types[TTYPE_AES_CCM] ||
2493 (custom_job_params.cipher_mode == TEST_CCM))
2494 fprintf(stderr, "CCM AAD = %"PRIu64"\n", ccm_aad_size);
2495
11fdf7f2
TL
2496 if (archs[ARCH_SSE]) {
2497 MB_MGR *p_mgr = alloc_mb_mgr(flags);
2498
2499 if (p_mgr == NULL) {
2500 fprintf(stderr, "Error allocating MB_MGR structure!\n");
2501 return EXIT_FAILURE;
2502 }
2503 init_mb_mgr_sse(p_mgr);
2504 fprintf(stderr, "%s SHA extensions (shani) for SSE arch\n",
2505 (p_mgr->features & IMB_FEATURE_SHANI) ?
2506 "Using" : "Not using");
2507 free_mb_mgr(p_mgr);
2508 }
2509
2510 memset(t_info, 0, sizeof(t_info));
f67539c2 2511 init_offsets(cache_type);
9f95a23c
TL
2512
2513 srand(ITER_SCALE_LONG + ITER_SCALE_SHORT + ITER_SCALE_SMOKE);
9f95a23c 2514
f67539c2
TL
2515 if (num_t > 1) {
2516 uint32_t n;
2517
2518 for (n = 0; n < (num_t - 1); n++, thread_info_p++) {
11fdf7f2
TL
2519 /* Set core if selected */
2520 if (core_mask) {
2521 core = next_core(core_mask, core);
2522 thread_info_p->core = core++;
2523 }
9f95a23c
TL
2524
2525 /* Allocate MB manager for each thread */
2526 thread_info_p->p_mgr = alloc_mb_mgr(flags);
2527 if (thread_info_p->p_mgr == NULL) {
2528 fprintf(stderr, "Failed to allocate MB_MGR "
f67539c2
TL
2529 "structure for thread %u!\n",
2530 (unsigned)(n + 1));
9f95a23c
TL
2531 exit(EXIT_FAILURE);
2532 }
11fdf7f2 2533#ifdef _WIN32
f67539c2 2534 threads[n] = (HANDLE)
11fdf7f2
TL
2535 _beginthread(&run_tests, 0,
2536 (void *)thread_info_p);
2537#else
2538 pthread_attr_t attr;
2539
2540 pthread_attr_init(&attr);
f67539c2 2541 pthread_create(&tids[n], &attr, run_tests,
11fdf7f2
TL
2542 (void *)thread_info_p);
2543#endif
2544 }
f67539c2 2545 }
11fdf7f2
TL
2546
2547 thread_info_p->print_info = 1;
9f95a23c
TL
2548 thread_info_p->p_mgr = alloc_mb_mgr(flags);
2549 if (thread_info_p->p_mgr == NULL) {
2550 fprintf(stderr, "Failed to allocate MB_MGR "
2551 "structure for main thread!\n");
9f95a23c
TL
2552 exit(EXIT_FAILURE);
2553 }
11fdf7f2
TL
2554 if (core_mask) {
2555 core = next_core(core_mask, core);
2556 thread_info_p->core = core;
2557 }
2558
2559 run_tests((void *)thread_info_p);
2560 if (num_t > 1) {
f67539c2
TL
2561 uint32_t n;
2562
11fdf7f2
TL
2563#ifdef _WIN32
2564 WaitForMultipleObjects(num_t, threads, FALSE, INFINITE);
2565#endif
f67539c2
TL
2566 for (n = 0; n < (num_t - 1); n++) {
2567 fprintf(stderr, "Waiting on thread %u to finish...\n",
2568 (unsigned)(n + 2));
11fdf7f2 2569#ifdef _WIN32
f67539c2 2570 CloseHandle(threads[n]);
11fdf7f2 2571#else
f67539c2 2572 pthread_join(tids[n], NULL);
11fdf7f2
TL
2573#endif
2574 }
2575 }
2576
2577 if (use_unhalted_cycles)
2578 machine_fini();
2579
11fdf7f2
TL
2580 return EXIT_SUCCESS;
2581}