99f5d3e0b0d96a53fc46a6f059e38c3ac220b243
[deb_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 #define NUM_SESSIONS 2048
47 #define SESS_MEMPOOL_CACHE_SIZE 64
48
49 const char *cperf_test_type_strs[] = {
50         [CPERF_TEST_TYPE_THROUGHPUT] = "throughput",
51         [CPERF_TEST_TYPE_LATENCY] = "latency",
52         [CPERF_TEST_TYPE_VERIFY] = "verify"
53 };
54
55 const char *cperf_op_type_strs[] = {
56         [CPERF_CIPHER_ONLY] = "cipher-only",
57         [CPERF_AUTH_ONLY] = "auth-only",
58         [CPERF_CIPHER_THEN_AUTH] = "cipher-then-auth",
59         [CPERF_AUTH_THEN_CIPHER] = "auth-then-cipher",
60         [CPERF_AEAD] = "aead"
61 };
62
63 const struct cperf_test cperf_testmap[] = {
64                 [CPERF_TEST_TYPE_THROUGHPUT] = {
65                                 cperf_throughput_test_constructor,
66                                 cperf_throughput_test_runner,
67                                 cperf_throughput_test_destructor
68                 },
69                 [CPERF_TEST_TYPE_LATENCY] = {
70                                 cperf_latency_test_constructor,
71                                 cperf_latency_test_runner,
72                                 cperf_latency_test_destructor
73                 },
74                 [CPERF_TEST_TYPE_VERIFY] = {
75                                 cperf_verify_test_constructor,
76                                 cperf_verify_test_runner,
77                                 cperf_verify_test_destructor
78                 }
79 };
80
81 static int
82 cperf_initialize_cryptodev(struct cperf_options *opts, uint8_t *enabled_cdevs,
83                         struct rte_mempool *session_pool_socket[])
84 {
85         uint8_t enabled_cdev_count = 0, nb_lcores, cdev_id;
86         unsigned int i;
87         int ret;
88
89         enabled_cdev_count = rte_cryptodev_devices_get(opts->device_type,
90                         enabled_cdevs, RTE_CRYPTO_MAX_DEVS);
91         if (enabled_cdev_count == 0) {
92                 printf("No crypto devices type %s available\n",
93                                 opts->device_type);
94                 return -EINVAL;
95         }
96
97         nb_lcores = rte_lcore_count() - 1;
98
99         if (enabled_cdev_count > nb_lcores) {
100                 printf("Number of capable crypto devices (%d) "
101                                 "has to be less or equal to number of slave "
102                                 "cores (%d)\n", enabled_cdev_count, nb_lcores);
103                 return -EINVAL;
104         }
105
106         /* Create a mempool shared by all the devices */
107         uint32_t max_sess_size = 0, sess_size;
108
109         for (cdev_id = 0; cdev_id < rte_cryptodev_count(); cdev_id++) {
110                 sess_size = rte_cryptodev_get_private_session_size(cdev_id);
111                 if (sess_size > max_sess_size)
112                         max_sess_size = sess_size;
113         }
114
115         for (i = 0; i < enabled_cdev_count &&
116                         i < RTE_CRYPTO_MAX_DEVS; i++) {
117                 cdev_id = enabled_cdevs[i];
118                 uint8_t socket_id = rte_cryptodev_socket_id(cdev_id);
119
120                 struct rte_cryptodev_config conf = {
121                                 .nb_queue_pairs = 1,
122                                 .socket_id = socket_id
123                 };
124
125                 struct rte_cryptodev_qp_conf qp_conf = {
126                                 .nb_descriptors = 2048
127                 };
128
129
130                 if (session_pool_socket[socket_id] == NULL) {
131                         char mp_name[RTE_MEMPOOL_NAMESIZE];
132                         struct rte_mempool *sess_mp;
133
134                         snprintf(mp_name, RTE_MEMPOOL_NAMESIZE,
135                                 "sess_mp_%u", socket_id);
136
137                         sess_mp = rte_mempool_create(mp_name,
138                                                 NUM_SESSIONS,
139                                                 max_sess_size,
140                                                 SESS_MEMPOOL_CACHE_SIZE,
141                                                 0, NULL, NULL, NULL,
142                                                 NULL, socket_id,
143                                                 0);
144
145                         if (sess_mp == NULL) {
146                                 printf("Cannot create session pool on socket %d\n",
147                                         socket_id);
148                                 return -ENOMEM;
149                         }
150
151                         printf("Allocated session pool on socket %d\n", socket_id);
152                         session_pool_socket[socket_id] = sess_mp;
153                 }
154
155                 ret = rte_cryptodev_configure(cdev_id, &conf);
156                 if (ret < 0) {
157                         printf("Failed to configure cryptodev %u", cdev_id);
158                         return -EINVAL;
159                 }
160
161                 ret = rte_cryptodev_queue_pair_setup(cdev_id, 0,
162                                 &qp_conf, socket_id,
163                                 session_pool_socket[socket_id]);
164                         if (ret < 0) {
165                                 printf("Failed to setup queue pair %u on "
166                                         "cryptodev %u", 0, cdev_id);
167                                 return -EINVAL;
168                         }
169
170                 ret = rte_cryptodev_start(cdev_id);
171                 if (ret < 0) {
172                         printf("Failed to start device %u: error %d\n",
173                                         cdev_id, ret);
174                         return -EPERM;
175                 }
176         }
177
178         return enabled_cdev_count;
179 }
180
181 static int
182 cperf_verify_devices_capabilities(struct cperf_options *opts,
183                 uint8_t *enabled_cdevs, uint8_t nb_cryptodevs)
184 {
185         struct rte_cryptodev_sym_capability_idx cap_idx;
186         const struct rte_cryptodev_symmetric_capability *capability;
187
188         uint8_t i, cdev_id;
189         int ret;
190
191         for (i = 0; i < nb_cryptodevs; i++) {
192
193                 cdev_id = enabled_cdevs[i];
194
195                 if (opts->op_type == CPERF_AUTH_ONLY ||
196                                 opts->op_type == CPERF_CIPHER_THEN_AUTH ||
197                                 opts->op_type == CPERF_AUTH_THEN_CIPHER) {
198
199                         cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
200                         cap_idx.algo.auth = opts->auth_algo;
201
202                         capability = rte_cryptodev_sym_capability_get(cdev_id,
203                                         &cap_idx);
204                         if (capability == NULL)
205                                 return -1;
206
207                         ret = rte_cryptodev_sym_capability_check_auth(
208                                         capability,
209                                         opts->auth_key_sz,
210                                         opts->digest_sz,
211                                         opts->auth_iv_sz);
212                         if (ret != 0)
213                                 return ret;
214                 }
215
216                 if (opts->op_type == CPERF_CIPHER_ONLY ||
217                                 opts->op_type == CPERF_CIPHER_THEN_AUTH ||
218                                 opts->op_type == CPERF_AUTH_THEN_CIPHER) {
219
220                         cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
221                         cap_idx.algo.cipher = opts->cipher_algo;
222
223                         capability = rte_cryptodev_sym_capability_get(cdev_id,
224                                         &cap_idx);
225                         if (capability == NULL)
226                                 return -1;
227
228                         ret = rte_cryptodev_sym_capability_check_cipher(
229                                         capability,
230                                         opts->cipher_key_sz,
231                                         opts->cipher_iv_sz);
232                         if (ret != 0)
233                                 return ret;
234                 }
235
236                 if (opts->op_type == CPERF_AEAD) {
237
238                         cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
239                         cap_idx.algo.aead = opts->aead_algo;
240
241                         capability = rte_cryptodev_sym_capability_get(cdev_id,
242                                         &cap_idx);
243                         if (capability == NULL)
244                                 return -1;
245
246                         ret = rte_cryptodev_sym_capability_check_aead(
247                                         capability,
248                                         opts->aead_key_sz,
249                                         opts->digest_sz,
250                                         opts->aead_aad_sz,
251                                         opts->aead_iv_sz);
252                         if (ret != 0)
253                                 return ret;
254                 }
255         }
256
257         return 0;
258 }
259
260 static int
261 cperf_check_test_vector(struct cperf_options *opts,
262                 struct cperf_test_vector *test_vec)
263 {
264         if (opts->op_type == CPERF_CIPHER_ONLY) {
265                 if (opts->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
266                         if (test_vec->plaintext.data == NULL)
267                                 return -1;
268                 } else if (opts->cipher_algo != RTE_CRYPTO_CIPHER_NULL) {
269                         if (test_vec->plaintext.data == NULL)
270                                 return -1;
271                         if (test_vec->plaintext.length < opts->max_buffer_size)
272                                 return -1;
273                         if (test_vec->ciphertext.data == NULL)
274                                 return -1;
275                         if (test_vec->ciphertext.length < opts->max_buffer_size)
276                                 return -1;
277                         if (test_vec->cipher_iv.data == NULL)
278                                 return -1;
279                         if (test_vec->cipher_iv.length != opts->cipher_iv_sz)
280                                 return -1;
281                         if (test_vec->cipher_key.data == NULL)
282                                 return -1;
283                         if (test_vec->cipher_key.length != opts->cipher_key_sz)
284                                 return -1;
285                 }
286         } else if (opts->op_type == CPERF_AUTH_ONLY) {
287                 if (opts->auth_algo != RTE_CRYPTO_AUTH_NULL) {
288                         if (test_vec->plaintext.data == NULL)
289                                 return -1;
290                         if (test_vec->plaintext.length < opts->max_buffer_size)
291                                 return -1;
292                         if (test_vec->auth_key.data == NULL)
293                                 return -1;
294                         if (test_vec->auth_key.length != opts->auth_key_sz)
295                                 return -1;
296                         if (test_vec->auth_iv.length != opts->auth_iv_sz)
297                                 return -1;
298                         /* Auth IV is only required for some algorithms */
299                         if (opts->auth_iv_sz && test_vec->auth_iv.data == NULL)
300                                 return -1;
301                         if (test_vec->digest.data == NULL)
302                                 return -1;
303                         if (test_vec->digest.length < opts->digest_sz)
304                                 return -1;
305                 }
306
307         } else if (opts->op_type == CPERF_CIPHER_THEN_AUTH ||
308                         opts->op_type == CPERF_AUTH_THEN_CIPHER) {
309                 if (opts->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
310                         if (test_vec->plaintext.data == NULL)
311                                 return -1;
312                         if (test_vec->plaintext.length < opts->max_buffer_size)
313                                 return -1;
314                 } else if (opts->cipher_algo != RTE_CRYPTO_CIPHER_NULL) {
315                         if (test_vec->plaintext.data == NULL)
316                                 return -1;
317                         if (test_vec->plaintext.length < opts->max_buffer_size)
318                                 return -1;
319                         if (test_vec->ciphertext.data == NULL)
320                                 return -1;
321                         if (test_vec->ciphertext.length < opts->max_buffer_size)
322                                 return -1;
323                         if (test_vec->cipher_iv.data == NULL)
324                                 return -1;
325                         if (test_vec->cipher_iv.length != opts->cipher_iv_sz)
326                                 return -1;
327                         if (test_vec->cipher_key.data == NULL)
328                                 return -1;
329                         if (test_vec->cipher_key.length != opts->cipher_key_sz)
330                                 return -1;
331                 }
332                 if (opts->auth_algo != RTE_CRYPTO_AUTH_NULL) {
333                         if (test_vec->auth_key.data == NULL)
334                                 return -1;
335                         if (test_vec->auth_key.length != opts->auth_key_sz)
336                                 return -1;
337                         if (test_vec->auth_iv.length != opts->auth_iv_sz)
338                                 return -1;
339                         /* Auth IV is only required for some algorithms */
340                         if (opts->auth_iv_sz && test_vec->auth_iv.data == NULL)
341                                 return -1;
342                         if (test_vec->digest.data == NULL)
343                                 return -1;
344                         if (test_vec->digest.length < opts->digest_sz)
345                                 return -1;
346                 }
347         } else if (opts->op_type == CPERF_AEAD) {
348                 if (test_vec->plaintext.data == NULL)
349                         return -1;
350                 if (test_vec->plaintext.length < opts->max_buffer_size)
351                         return -1;
352                 if (test_vec->ciphertext.data == NULL)
353                         return -1;
354                 if (test_vec->ciphertext.length < opts->max_buffer_size)
355                         return -1;
356                 if (test_vec->aead_iv.data == NULL)
357                         return -1;
358                 if (test_vec->aead_iv.length != opts->aead_iv_sz)
359                         return -1;
360                 if (test_vec->aad.data == NULL)
361                         return -1;
362                 if (test_vec->aad.length != opts->aead_aad_sz)
363                         return -1;
364                 if (test_vec->digest.data == NULL)
365                         return -1;
366                 if (test_vec->digest.length < opts->digest_sz)
367                         return -1;
368         }
369         return 0;
370 }
371
372 int
373 main(int argc, char **argv)
374 {
375         struct cperf_options opts = {0};
376         struct cperf_test_vector *t_vec = NULL;
377         struct cperf_op_fns op_fns;
378
379         void *ctx[RTE_MAX_LCORE] = { };
380         struct rte_mempool *session_pool_socket[RTE_MAX_NUMA_NODES] = { 0 };
381
382         int nb_cryptodevs = 0;
383         uint8_t cdev_id, i;
384         uint8_t enabled_cdevs[RTE_CRYPTO_MAX_DEVS] = { 0 };
385
386         uint8_t buffer_size_idx = 0;
387
388         int ret;
389         uint32_t lcore_id;
390
391         /* Initialise DPDK EAL */
392         ret = rte_eal_init(argc, argv);
393         if (ret < 0)
394                 rte_exit(EXIT_FAILURE, "Invalid EAL arguments!\n");
395         argc -= ret;
396         argv += ret;
397
398         cperf_options_default(&opts);
399
400         ret = cperf_options_parse(&opts, argc, argv);
401         if (ret) {
402                 RTE_LOG(ERR, USER1, "Parsing on or more user options failed\n");
403                 goto err;
404         }
405
406         ret = cperf_options_check(&opts);
407         if (ret) {
408                 RTE_LOG(ERR, USER1,
409                                 "Checking on or more user options failed\n");
410                 goto err;
411         }
412
413         if (!opts.silent)
414                 cperf_options_dump(&opts);
415
416         nb_cryptodevs = cperf_initialize_cryptodev(&opts, enabled_cdevs,
417                         session_pool_socket);
418         if (nb_cryptodevs < 1) {
419                 RTE_LOG(ERR, USER1, "Failed to initialise requested crypto "
420                                 "device type\n");
421                 nb_cryptodevs = 0;
422                 goto err;
423         }
424
425         ret = cperf_verify_devices_capabilities(&opts, enabled_cdevs,
426                         nb_cryptodevs);
427         if (ret) {
428                 RTE_LOG(ERR, USER1, "Crypto device type does not support "
429                                 "capabilities requested\n");
430                 goto err;
431         }
432
433         if (opts.test_file != NULL) {
434                 t_vec = cperf_test_vector_get_from_file(&opts);
435                 if (t_vec == NULL) {
436                         RTE_LOG(ERR, USER1,
437                                         "Failed to create test vector for"
438                                         " specified file\n");
439                         goto err;
440                 }
441
442                 if (cperf_check_test_vector(&opts, t_vec)) {
443                         RTE_LOG(ERR, USER1, "Incomplete necessary test vectors"
444                                         "\n");
445                         goto err;
446                 }
447         } else {
448                 t_vec = cperf_test_vector_get_dummy(&opts);
449                 if (t_vec == NULL) {
450                         RTE_LOG(ERR, USER1,
451                                         "Failed to create test vector for"
452                                         " specified algorithms\n");
453                         goto err;
454                 }
455         }
456
457         ret = cperf_get_op_functions(&opts, &op_fns);
458         if (ret) {
459                 RTE_LOG(ERR, USER1, "Failed to find function ops set for "
460                                 "specified algorithms combination\n");
461                 goto err;
462         }
463
464         if (!opts.silent)
465                 show_test_vector(t_vec);
466
467         i = 0;
468         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
469
470                 if (i == nb_cryptodevs)
471                         break;
472
473                 cdev_id = enabled_cdevs[i];
474
475                 uint8_t socket_id = rte_cryptodev_socket_id(cdev_id);
476
477                 ctx[cdev_id] = cperf_testmap[opts.test].constructor(
478                                 session_pool_socket[socket_id], cdev_id, 0,
479                                 &opts, t_vec, &op_fns);
480                 if (ctx[cdev_id] == NULL) {
481                         RTE_LOG(ERR, USER1, "Test run constructor failed\n");
482                         goto err;
483                 }
484                 i++;
485         }
486
487         /* Get first size from range or list */
488         if (opts.inc_buffer_size != 0)
489                 opts.test_buffer_size = opts.min_buffer_size;
490         else
491                 opts.test_buffer_size = opts.buffer_size_list[0];
492
493         while (opts.test_buffer_size <= opts.max_buffer_size) {
494                 i = 0;
495                 RTE_LCORE_FOREACH_SLAVE(lcore_id) {
496
497                         if (i == nb_cryptodevs)
498                                 break;
499
500                         cdev_id = enabled_cdevs[i];
501
502                         rte_eal_remote_launch(cperf_testmap[opts.test].runner,
503                                 ctx[cdev_id], lcore_id);
504                         i++;
505                 }
506                 i = 0;
507                 RTE_LCORE_FOREACH_SLAVE(lcore_id) {
508
509                         if (i == nb_cryptodevs)
510                                 break;
511                         rte_eal_wait_lcore(lcore_id);
512                         i++;
513                 }
514
515                 /* Get next size from range or list */
516                 if (opts.inc_buffer_size != 0)
517                         opts.test_buffer_size += opts.inc_buffer_size;
518                 else {
519                         if (++buffer_size_idx == opts.buffer_size_count)
520                                 break;
521                         opts.test_buffer_size = opts.buffer_size_list[buffer_size_idx];
522                 }
523         }
524
525         i = 0;
526         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
527
528                 if (i == nb_cryptodevs)
529                         break;
530
531                 cdev_id = enabled_cdevs[i];
532
533                 cperf_testmap[opts.test].destructor(ctx[cdev_id]);
534                 i++;
535         }
536
537         free_test_vector(t_vec, &opts);
538
539         printf("\n");
540         return EXIT_SUCCESS;
541
542 err:
543         i = 0;
544         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
545                 if (i == nb_cryptodevs)
546                         break;
547
548                 cdev_id = enabled_cdevs[i];
549
550                 if (ctx[cdev_id] && cperf_testmap[opts.test].destructor)
551                         cperf_testmap[opts.test].destructor(ctx[cdev_id]);
552                 i++;
553         }
554
555         free_test_vector(t_vec, &opts);
556
557         printf("\n");
558         return EXIT_FAILURE;
559 }