app/test-crypto-perf: add AEAD parameters
[dpdk.git] / app / test-crypto-perf / main.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
5  *
6  *   Redistribution and use in source and binary forms, with or without
7  *   modification, are permitted provided that the following conditions
8  *   are met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above copyright
13  *       notice, this list of conditions and the following disclaimer in
14  *       the documentation and/or other materials provided with the
15  *       distribution.
16  *     * Neither the name of Intel Corporation nor the names of its
17  *       contributors may be used to endorse or promote products derived
18  *       from this software without specific prior written permission.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include <stdio.h>
34 #include <unistd.h>
35
36 #include <rte_eal.h>
37 #include <rte_cryptodev.h>
38
39 #include "cperf.h"
40 #include "cperf_options.h"
41 #include "cperf_test_vector_parsing.h"
42 #include "cperf_test_throughput.h"
43 #include "cperf_test_latency.h"
44 #include "cperf_test_verify.h"
45
46 const char *cperf_test_type_strs[] = {
47         [CPERF_TEST_TYPE_THROUGHPUT] = "throughput",
48         [CPERF_TEST_TYPE_LATENCY] = "latency",
49         [CPERF_TEST_TYPE_VERIFY] = "verify"
50 };
51
52 const char *cperf_op_type_strs[] = {
53         [CPERF_CIPHER_ONLY] = "cipher-only",
54         [CPERF_AUTH_ONLY] = "auth-only",
55         [CPERF_CIPHER_THEN_AUTH] = "cipher-then-auth",
56         [CPERF_AUTH_THEN_CIPHER] = "auth-then-cipher",
57         [CPERF_AEAD] = "aead"
58 };
59
60 const struct cperf_test cperf_testmap[] = {
61                 [CPERF_TEST_TYPE_THROUGHPUT] = {
62                                 cperf_throughput_test_constructor,
63                                 cperf_throughput_test_runner,
64                                 cperf_throughput_test_destructor
65                 },
66                 [CPERF_TEST_TYPE_LATENCY] = {
67                                 cperf_latency_test_constructor,
68                                 cperf_latency_test_runner,
69                                 cperf_latency_test_destructor
70                 },
71                 [CPERF_TEST_TYPE_VERIFY] = {
72                                 cperf_verify_test_constructor,
73                                 cperf_verify_test_runner,
74                                 cperf_verify_test_destructor
75                 }
76 };
77
78 static int
79 cperf_initialize_cryptodev(struct cperf_options *opts, uint8_t *enabled_cdevs)
80 {
81         uint8_t cdev_id, enabled_cdev_count = 0, nb_lcores;
82         int ret;
83
84         enabled_cdev_count = rte_cryptodev_devices_get(opts->device_type,
85                         enabled_cdevs, RTE_CRYPTO_MAX_DEVS);
86         if (enabled_cdev_count == 0) {
87                 printf("No crypto devices type %s available\n",
88                                 opts->device_type);
89                 return -EINVAL;
90         }
91
92         nb_lcores = rte_lcore_count() - 1;
93
94         if (enabled_cdev_count > nb_lcores) {
95                 printf("Number of capable crypto devices (%d) "
96                                 "has to be less or equal to number of slave "
97                                 "cores (%d)\n", enabled_cdev_count, nb_lcores);
98                 return -EINVAL;
99         }
100
101         for (cdev_id = 0; cdev_id < enabled_cdev_count &&
102                         cdev_id < RTE_CRYPTO_MAX_DEVS; cdev_id++) {
103
104                 struct rte_cryptodev_config conf = {
105                                 .nb_queue_pairs = 1,
106                                 .socket_id = SOCKET_ID_ANY,
107                                 .session_mp = {
108                                         .nb_objs = 2048,
109                                         .cache_size = 64
110                                 }
111                         };
112                 struct rte_cryptodev_qp_conf qp_conf = {
113                                 .nb_descriptors = 2048
114                 };
115
116                 ret = rte_cryptodev_configure(enabled_cdevs[cdev_id], &conf);
117                 if (ret < 0) {
118                         printf("Failed to configure cryptodev %u",
119                                         enabled_cdevs[cdev_id]);
120                         return -EINVAL;
121                 }
122
123                 ret = rte_cryptodev_queue_pair_setup(enabled_cdevs[cdev_id], 0,
124                                 &qp_conf, SOCKET_ID_ANY);
125                         if (ret < 0) {
126                                 printf("Failed to setup queue pair %u on "
127                                         "cryptodev %u", 0, cdev_id);
128                                 return -EINVAL;
129                         }
130
131                 ret = rte_cryptodev_start(enabled_cdevs[cdev_id]);
132                 if (ret < 0) {
133                         printf("Failed to start device %u: error %d\n",
134                                         enabled_cdevs[cdev_id], ret);
135                         return -EPERM;
136                 }
137         }
138
139         return enabled_cdev_count;
140 }
141
142 static int
143 cperf_verify_devices_capabilities(struct cperf_options *opts,
144                 uint8_t *enabled_cdevs, uint8_t nb_cryptodevs)
145 {
146         struct rte_cryptodev_sym_capability_idx cap_idx;
147         const struct rte_cryptodev_symmetric_capability *capability;
148
149         uint8_t i, cdev_id;
150         int ret;
151
152         for (i = 0; i < nb_cryptodevs; i++) {
153
154                 cdev_id = enabled_cdevs[i];
155
156                 if (opts->op_type == CPERF_AUTH_ONLY ||
157                                 opts->op_type == CPERF_CIPHER_THEN_AUTH ||
158                                 opts->op_type == CPERF_AUTH_THEN_CIPHER) {
159
160                         cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
161                         cap_idx.algo.auth = opts->auth_algo;
162
163                         capability = rte_cryptodev_sym_capability_get(cdev_id,
164                                         &cap_idx);
165                         if (capability == NULL)
166                                 return -1;
167
168                         ret = rte_cryptodev_sym_capability_check_auth(
169                                         capability,
170                                         opts->auth_key_sz,
171                                         opts->digest_sz,
172                                         0,
173                                         opts->auth_iv_sz);
174                         if (ret != 0)
175                                 return ret;
176                 }
177
178                 if (opts->op_type == CPERF_CIPHER_ONLY ||
179                                 opts->op_type == CPERF_CIPHER_THEN_AUTH ||
180                                 opts->op_type == CPERF_AUTH_THEN_CIPHER) {
181
182                         cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
183                         cap_idx.algo.cipher = opts->cipher_algo;
184
185                         capability = rte_cryptodev_sym_capability_get(cdev_id,
186                                         &cap_idx);
187                         if (capability == NULL)
188                                 return -1;
189
190                         ret = rte_cryptodev_sym_capability_check_cipher(
191                                         capability,
192                                         opts->cipher_key_sz,
193                                         opts->cipher_iv_sz);
194                         if (ret != 0)
195                                 return ret;
196                 }
197
198                 if (opts->op_type == CPERF_AEAD) {
199
200                         cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
201                         cap_idx.algo.aead = opts->aead_algo;
202
203                         capability = rte_cryptodev_sym_capability_get(cdev_id,
204                                         &cap_idx);
205                         if (capability == NULL)
206                                 return -1;
207
208                         ret = rte_cryptodev_sym_capability_check_aead(
209                                         capability,
210                                         opts->aead_key_sz,
211                                         opts->digest_sz,
212                                         opts->aead_aad_sz,
213                                         opts->aead_iv_sz);
214                         if (ret != 0)
215                                 return ret;
216                 }
217         }
218
219         return 0;
220 }
221
222 static int
223 cperf_check_test_vector(struct cperf_options *opts,
224                 struct cperf_test_vector *test_vec)
225 {
226         if (opts->op_type == CPERF_CIPHER_ONLY) {
227                 if (opts->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
228                         if (test_vec->plaintext.data == NULL)
229                                 return -1;
230                 } else if (opts->cipher_algo != RTE_CRYPTO_CIPHER_NULL) {
231                         if (test_vec->plaintext.data == NULL)
232                                 return -1;
233                         if (test_vec->plaintext.length < opts->max_buffer_size)
234                                 return -1;
235                         if (test_vec->ciphertext.data == NULL)
236                                 return -1;
237                         if (test_vec->ciphertext.length < opts->max_buffer_size)
238                                 return -1;
239                         if (test_vec->cipher_iv.data == NULL)
240                                 return -1;
241                         if (test_vec->cipher_iv.length != opts->cipher_iv_sz)
242                                 return -1;
243                         if (test_vec->cipher_key.data == NULL)
244                                 return -1;
245                         if (test_vec->cipher_key.length != opts->cipher_key_sz)
246                                 return -1;
247                 }
248         } else if (opts->op_type == CPERF_AUTH_ONLY) {
249                 if (opts->auth_algo != RTE_CRYPTO_AUTH_NULL) {
250                         if (test_vec->plaintext.data == NULL)
251                                 return -1;
252                         if (test_vec->plaintext.length < opts->max_buffer_size)
253                                 return -1;
254                         if (test_vec->auth_key.data == NULL)
255                                 return -1;
256                         if (test_vec->auth_key.length != opts->auth_key_sz)
257                                 return -1;
258                         if (test_vec->auth_iv.length != opts->auth_iv_sz)
259                                 return -1;
260                         /* Auth IV is only required for some algorithms */
261                         if (opts->auth_iv_sz && test_vec->auth_iv.data == NULL)
262                                 return -1;
263                         if (test_vec->digest.data == NULL)
264                                 return -1;
265                         if (test_vec->digest.length < opts->digest_sz)
266                                 return -1;
267                 }
268
269         } else if (opts->op_type == CPERF_CIPHER_THEN_AUTH ||
270                         opts->op_type == CPERF_AUTH_THEN_CIPHER) {
271                 if (opts->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
272                         if (test_vec->plaintext.data == NULL)
273                                 return -1;
274                         if (test_vec->plaintext.length < opts->max_buffer_size)
275                                 return -1;
276                 } else if (opts->cipher_algo != RTE_CRYPTO_CIPHER_NULL) {
277                         if (test_vec->plaintext.data == NULL)
278                                 return -1;
279                         if (test_vec->plaintext.length < opts->max_buffer_size)
280                                 return -1;
281                         if (test_vec->ciphertext.data == NULL)
282                                 return -1;
283                         if (test_vec->ciphertext.length < opts->max_buffer_size)
284                                 return -1;
285                         if (test_vec->cipher_iv.data == NULL)
286                                 return -1;
287                         if (test_vec->cipher_iv.length != opts->cipher_iv_sz)
288                                 return -1;
289                         if (test_vec->cipher_key.data == NULL)
290                                 return -1;
291                         if (test_vec->cipher_key.length != opts->cipher_key_sz)
292                                 return -1;
293                 }
294                 if (opts->auth_algo != RTE_CRYPTO_AUTH_NULL) {
295                         if (test_vec->auth_key.data == NULL)
296                                 return -1;
297                         if (test_vec->auth_key.length != opts->auth_key_sz)
298                                 return -1;
299                         if (test_vec->auth_iv.length != opts->auth_iv_sz)
300                                 return -1;
301                         /* Auth IV is only required for some algorithms */
302                         if (opts->auth_iv_sz && test_vec->auth_iv.data == NULL)
303                                 return -1;
304                         if (test_vec->digest.data == NULL)
305                                 return -1;
306                         if (test_vec->digest.length < opts->digest_sz)
307                                 return -1;
308                 }
309         } else if (opts->op_type == CPERF_AEAD) {
310                 if (test_vec->plaintext.data == NULL)
311                         return -1;
312                 if (test_vec->plaintext.length < opts->max_buffer_size)
313                         return -1;
314                 if (test_vec->ciphertext.data == NULL)
315                         return -1;
316                 if (test_vec->ciphertext.length < opts->max_buffer_size)
317                         return -1;
318                 if (test_vec->aead_iv.data == NULL)
319                         return -1;
320                 if (test_vec->aead_iv.length != opts->aead_iv_sz)
321                         return -1;
322                 if (test_vec->aad.data == NULL)
323                         return -1;
324                 if (test_vec->aad.length != opts->aead_aad_sz)
325                         return -1;
326                 if (test_vec->digest.data == NULL)
327                         return -1;
328                 if (test_vec->digest.length < opts->digest_sz)
329                         return -1;
330         }
331         return 0;
332 }
333
334 int
335 main(int argc, char **argv)
336 {
337         struct cperf_options opts = {0};
338         struct cperf_test_vector *t_vec = NULL;
339         struct cperf_op_fns op_fns;
340
341         void *ctx[RTE_MAX_LCORE] = { };
342
343         int nb_cryptodevs = 0;
344         uint8_t cdev_id, i;
345         uint8_t enabled_cdevs[RTE_CRYPTO_MAX_DEVS] = { 0 };
346
347         uint8_t buffer_size_idx = 0;
348
349         int ret;
350         uint32_t lcore_id;
351
352         /* Initialise DPDK EAL */
353         ret = rte_eal_init(argc, argv);
354         if (ret < 0)
355                 rte_exit(EXIT_FAILURE, "Invalid EAL arguments!\n");
356         argc -= ret;
357         argv += ret;
358
359         cperf_options_default(&opts);
360
361         ret = cperf_options_parse(&opts, argc, argv);
362         if (ret) {
363                 RTE_LOG(ERR, USER1, "Parsing on or more user options failed\n");
364                 goto err;
365         }
366
367         ret = cperf_options_check(&opts);
368         if (ret) {
369                 RTE_LOG(ERR, USER1,
370                                 "Checking on or more user options failed\n");
371                 goto err;
372         }
373
374         if (!opts.silent)
375                 cperf_options_dump(&opts);
376
377         nb_cryptodevs = cperf_initialize_cryptodev(&opts, enabled_cdevs);
378         if (nb_cryptodevs < 1) {
379                 RTE_LOG(ERR, USER1, "Failed to initialise requested crypto "
380                                 "device type\n");
381                 nb_cryptodevs = 0;
382                 goto err;
383         }
384
385         ret = cperf_verify_devices_capabilities(&opts, enabled_cdevs,
386                         nb_cryptodevs);
387         if (ret) {
388                 RTE_LOG(ERR, USER1, "Crypto device type does not support "
389                                 "capabilities requested\n");
390                 goto err;
391         }
392
393         if (opts.test_file != NULL) {
394                 t_vec = cperf_test_vector_get_from_file(&opts);
395                 if (t_vec == NULL) {
396                         RTE_LOG(ERR, USER1,
397                                         "Failed to create test vector for"
398                                         " specified file\n");
399                         goto err;
400                 }
401
402                 if (cperf_check_test_vector(&opts, t_vec)) {
403                         RTE_LOG(ERR, USER1, "Incomplete necessary test vectors"
404                                         "\n");
405                         goto err;
406                 }
407         } else {
408                 t_vec = cperf_test_vector_get_dummy(&opts);
409                 if (t_vec == NULL) {
410                         RTE_LOG(ERR, USER1,
411                                         "Failed to create test vector for"
412                                         " specified algorithms\n");
413                         goto err;
414                 }
415         }
416
417         ret = cperf_get_op_functions(&opts, &op_fns);
418         if (ret) {
419                 RTE_LOG(ERR, USER1, "Failed to find function ops set for "
420                                 "specified algorithms combination\n");
421                 goto err;
422         }
423
424         if (!opts.silent)
425                 show_test_vector(t_vec);
426
427         i = 0;
428         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
429
430                 if (i == nb_cryptodevs)
431                         break;
432
433                 cdev_id = enabled_cdevs[i];
434
435                 ctx[cdev_id] = cperf_testmap[opts.test].constructor(cdev_id, 0,
436                                 &opts, t_vec, &op_fns);
437                 if (ctx[cdev_id] == NULL) {
438                         RTE_LOG(ERR, USER1, "Test run constructor failed\n");
439                         goto err;
440                 }
441                 i++;
442         }
443
444         /* Get first size from range or list */
445         if (opts.inc_buffer_size != 0)
446                 opts.test_buffer_size = opts.min_buffer_size;
447         else
448                 opts.test_buffer_size = opts.buffer_size_list[0];
449
450         while (opts.test_buffer_size <= opts.max_buffer_size) {
451                 i = 0;
452                 RTE_LCORE_FOREACH_SLAVE(lcore_id) {
453
454                         if (i == nb_cryptodevs)
455                                 break;
456
457                         cdev_id = enabled_cdevs[i];
458
459                         rte_eal_remote_launch(cperf_testmap[opts.test].runner,
460                                 ctx[cdev_id], lcore_id);
461                         i++;
462                 }
463                 rte_eal_mp_wait_lcore();
464
465                 /* Get next size from range or list */
466                 if (opts.inc_buffer_size != 0)
467                         opts.test_buffer_size += opts.inc_buffer_size;
468                 else {
469                         if (++buffer_size_idx == opts.buffer_size_count)
470                                 break;
471                         opts.test_buffer_size = opts.buffer_size_list[buffer_size_idx];
472                 }
473         }
474
475         i = 0;
476         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
477
478                 if (i == nb_cryptodevs)
479                         break;
480
481                 cdev_id = enabled_cdevs[i];
482
483                 cperf_testmap[opts.test].destructor(ctx[cdev_id]);
484                 i++;
485         }
486
487         free_test_vector(t_vec, &opts);
488
489         printf("\n");
490         return EXIT_SUCCESS;
491
492 err:
493         i = 0;
494         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
495                 if (i == nb_cryptodevs)
496                         break;
497
498                 cdev_id = enabled_cdevs[i];
499
500                 if (ctx[cdev_id] && cperf_testmap[opts.test].destructor)
501                         cperf_testmap[opts.test].destructor(ctx[cdev_id]);
502                 i++;
503         }
504
505         free_test_vector(t_vec, &opts);
506
507         printf("\n");
508         return EXIT_FAILURE;
509 }