9ec2a4b43bfd8875aa9d5fcb2e5c8ca44e2f5172
[deb_dpdk.git] / app / test-crypto-perf / main.c
1 #include <stdio.h>
2 #include <unistd.h>
3
4 #include <rte_eal.h>
5 #include <rte_cryptodev.h>
6
7 #include "cperf.h"
8 #include "cperf_options.h"
9 #include "cperf_test_vector_parsing.h"
10 #include "cperf_test_throughput.h"
11 #include "cperf_test_latency.h"
12 #include "cperf_test_verify.h"
13
14 const char *cperf_test_type_strs[] = {
15         [CPERF_TEST_TYPE_THROUGHPUT] = "throughput",
16         [CPERF_TEST_TYPE_LATENCY] = "latency",
17         [CPERF_TEST_TYPE_VERIFY] = "verify"
18 };
19
20 const char *cperf_op_type_strs[] = {
21         [CPERF_CIPHER_ONLY] = "cipher-only",
22         [CPERF_AUTH_ONLY] = "auth-only",
23         [CPERF_CIPHER_THEN_AUTH] = "cipher-then-auth",
24         [CPERF_AUTH_THEN_CIPHER] = "auth-then-cipher",
25         [CPERF_AEAD] = "aead"
26 };
27
28 const struct cperf_test cperf_testmap[] = {
29                 [CPERF_TEST_TYPE_THROUGHPUT] = {
30                                 cperf_throughput_test_constructor,
31                                 cperf_throughput_test_runner,
32                                 cperf_throughput_test_destructor
33                 },
34                 [CPERF_TEST_TYPE_LATENCY] = {
35                                 cperf_latency_test_constructor,
36                                 cperf_latency_test_runner,
37                                 cperf_latency_test_destructor
38                 },
39                 [CPERF_TEST_TYPE_VERIFY] = {
40                                 cperf_verify_test_constructor,
41                                 cperf_verify_test_runner,
42                                 cperf_verify_test_destructor
43                 }
44 };
45
46 static int
47 cperf_initialize_cryptodev(struct cperf_options *opts, uint8_t *enabled_cdevs)
48 {
49         uint8_t cdev_id, enabled_cdev_count = 0, nb_lcores;
50         int ret;
51
52         enabled_cdev_count = rte_cryptodev_devices_get(opts->device_type,
53                         enabled_cdevs, RTE_CRYPTO_MAX_DEVS);
54         if (enabled_cdev_count == 0) {
55                 printf("No crypto devices type %s available\n",
56                                 opts->device_type);
57                 return -EINVAL;
58         }
59
60         nb_lcores = rte_lcore_count() - 1;
61
62         if (enabled_cdev_count > nb_lcores) {
63                 printf("Number of capable crypto devices (%d) "
64                                 "has to be less or equal to number of slave "
65                                 "cores (%d)\n", enabled_cdev_count, nb_lcores);
66                 return -EINVAL;
67         }
68
69         for (cdev_id = 0; cdev_id < enabled_cdev_count &&
70                         cdev_id < RTE_CRYPTO_MAX_DEVS; cdev_id++) {
71
72                 struct rte_cryptodev_config conf = {
73                                 .nb_queue_pairs = 1,
74                                 .socket_id = SOCKET_ID_ANY,
75                                 .session_mp = {
76                                         .nb_objs = 2048,
77                                         .cache_size = 64
78                                 }
79                         };
80                 struct rte_cryptodev_qp_conf qp_conf = {
81                                 .nb_descriptors = 2048
82                 };
83
84                 ret = rte_cryptodev_configure(enabled_cdevs[cdev_id], &conf);
85                 if (ret < 0) {
86                         printf("Failed to configure cryptodev %u",
87                                         enabled_cdevs[cdev_id]);
88                         return -EINVAL;
89                 }
90
91                 ret = rte_cryptodev_queue_pair_setup(enabled_cdevs[cdev_id], 0,
92                                 &qp_conf, SOCKET_ID_ANY);
93                         if (ret < 0) {
94                                 printf("Failed to setup queue pair %u on "
95                                         "cryptodev %u", 0, cdev_id);
96                                 return -EINVAL;
97                         }
98
99                 ret = rte_cryptodev_start(enabled_cdevs[cdev_id]);
100                 if (ret < 0) {
101                         printf("Failed to start device %u: error %d\n",
102                                         enabled_cdevs[cdev_id], ret);
103                         return -EPERM;
104                 }
105         }
106
107         return enabled_cdev_count;
108 }
109
110 static int
111 cperf_verify_devices_capabilities(struct cperf_options *opts,
112                 uint8_t *enabled_cdevs, uint8_t nb_cryptodevs)
113 {
114         struct rte_cryptodev_sym_capability_idx cap_idx;
115         const struct rte_cryptodev_symmetric_capability *capability;
116
117         uint8_t i, cdev_id;
118         int ret;
119
120         for (i = 0; i < nb_cryptodevs; i++) {
121
122                 cdev_id = enabled_cdevs[i];
123
124                 if (opts->op_type == CPERF_AUTH_ONLY ||
125                                 opts->op_type == CPERF_CIPHER_THEN_AUTH ||
126                                 opts->op_type == CPERF_AUTH_THEN_CIPHER ||
127                                 opts->op_type == CPERF_AEAD)  {
128
129                         cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
130                         cap_idx.algo.auth = opts->auth_algo;
131
132                         capability = rte_cryptodev_sym_capability_get(cdev_id,
133                                         &cap_idx);
134                         if (capability == NULL)
135                                 return -1;
136
137                         ret = rte_cryptodev_sym_capability_check_auth(
138                                         capability,
139                                         opts->auth_key_sz,
140                                         opts->auth_digest_sz,
141                                         opts->auth_aad_sz);
142                         if (ret != 0)
143                                 return ret;
144                 }
145
146                 if (opts->op_type == CPERF_CIPHER_ONLY ||
147                                 opts->op_type == CPERF_CIPHER_THEN_AUTH ||
148                                 opts->op_type == CPERF_AUTH_THEN_CIPHER ||
149                                 opts->op_type == CPERF_AEAD) {
150
151                         cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
152                         cap_idx.algo.cipher = opts->cipher_algo;
153
154                         capability = rte_cryptodev_sym_capability_get(cdev_id,
155                                         &cap_idx);
156                         if (capability == NULL)
157                                 return -1;
158
159                         ret = rte_cryptodev_sym_capability_check_cipher(
160                                         capability,
161                                         opts->cipher_key_sz,
162                                         opts->cipher_iv_sz);
163                         if (ret != 0)
164                                 return ret;
165                 }
166         }
167
168         return 0;
169 }
170
171 static int
172 cperf_check_test_vector(struct cperf_options *opts,
173                 struct cperf_test_vector *test_vec)
174 {
175         if (opts->op_type == CPERF_CIPHER_ONLY) {
176                 if (opts->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
177                         if (test_vec->plaintext.data == NULL)
178                                 return -1;
179                 } else if (opts->cipher_algo != RTE_CRYPTO_CIPHER_NULL) {
180                         if (test_vec->plaintext.data == NULL)
181                                 return -1;
182                         if (test_vec->plaintext.length < opts->max_buffer_size)
183                                 return -1;
184                         if (test_vec->ciphertext.data == NULL)
185                                 return -1;
186                         if (test_vec->ciphertext.length < opts->max_buffer_size)
187                                 return -1;
188                         if (test_vec->iv.data == NULL)
189                                 return -1;
190                         if (test_vec->iv.length != opts->cipher_iv_sz)
191                                 return -1;
192                         if (test_vec->cipher_key.data == NULL)
193                                 return -1;
194                         if (test_vec->cipher_key.length != opts->cipher_key_sz)
195                                 return -1;
196                 }
197         } else if (opts->op_type == CPERF_AUTH_ONLY) {
198                 if (opts->auth_algo != RTE_CRYPTO_AUTH_NULL) {
199                         if (test_vec->plaintext.data == NULL)
200                                 return -1;
201                         if (test_vec->plaintext.length < opts->max_buffer_size)
202                                 return -1;
203                         if (test_vec->auth_key.data == NULL)
204                                 return -1;
205                         if (test_vec->auth_key.length != opts->auth_key_sz)
206                                 return -1;
207                         if (test_vec->digest.data == NULL)
208                                 return -1;
209                         if (test_vec->digest.length < opts->auth_digest_sz)
210                                 return -1;
211                 }
212
213         } else if (opts->op_type == CPERF_CIPHER_THEN_AUTH ||
214                         opts->op_type == CPERF_AUTH_THEN_CIPHER) {
215                 if (opts->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
216                         if (test_vec->plaintext.data == NULL)
217                                 return -1;
218                         if (test_vec->plaintext.length < opts->max_buffer_size)
219                                 return -1;
220                 } else if (opts->cipher_algo != RTE_CRYPTO_CIPHER_NULL) {
221                         if (test_vec->plaintext.data == NULL)
222                                 return -1;
223                         if (test_vec->plaintext.length < opts->max_buffer_size)
224                                 return -1;
225                         if (test_vec->ciphertext.data == NULL)
226                                 return -1;
227                         if (test_vec->ciphertext.length < opts->max_buffer_size)
228                                 return -1;
229                         if (test_vec->iv.data == NULL)
230                                 return -1;
231                         if (test_vec->iv.length != opts->cipher_iv_sz)
232                                 return -1;
233                         if (test_vec->cipher_key.data == NULL)
234                                 return -1;
235                         if (test_vec->cipher_key.length != opts->cipher_key_sz)
236                                 return -1;
237                 }
238                 if (opts->auth_algo != RTE_CRYPTO_AUTH_NULL) {
239                         if (test_vec->auth_key.data == NULL)
240                                 return -1;
241                         if (test_vec->auth_key.length != opts->auth_key_sz)
242                                 return -1;
243                         if (test_vec->digest.data == NULL)
244                                 return -1;
245                         if (test_vec->digest.length < opts->auth_digest_sz)
246                                 return -1;
247                 }
248         } else if (opts->op_type == CPERF_AEAD) {
249                 if (test_vec->plaintext.data == NULL)
250                         return -1;
251                 if (test_vec->plaintext.length < opts->max_buffer_size)
252                         return -1;
253                 if (test_vec->ciphertext.data == NULL)
254                         return -1;
255                 if (test_vec->ciphertext.length < opts->max_buffer_size)
256                         return -1;
257                 if (test_vec->aad.data == NULL)
258                         return -1;
259                 if (test_vec->aad.length != opts->auth_aad_sz)
260                         return -1;
261                 if (test_vec->digest.data == NULL)
262                         return -1;
263                 if (test_vec->digest.length < opts->auth_digest_sz)
264                         return -1;
265         }
266         return 0;
267 }
268
269 int
270 main(int argc, char **argv)
271 {
272         struct cperf_options opts = {0};
273         struct cperf_test_vector *t_vec = NULL;
274         struct cperf_op_fns op_fns;
275
276         void *ctx[RTE_MAX_LCORE] = { };
277
278         int nb_cryptodevs = 0;
279         uint8_t cdev_id, i;
280         uint8_t enabled_cdevs[RTE_CRYPTO_MAX_DEVS] = { 0 };
281
282         uint8_t buffer_size_idx = 0;
283
284         int ret;
285         uint32_t lcore_id;
286
287         /* Initialise DPDK EAL */
288         ret = rte_eal_init(argc, argv);
289         if (ret < 0)
290                 rte_exit(EXIT_FAILURE, "Invalid EAL arguments!\n");
291         argc -= ret;
292         argv += ret;
293
294         cperf_options_default(&opts);
295
296         ret = cperf_options_parse(&opts, argc, argv);
297         if (ret) {
298                 RTE_LOG(ERR, USER1, "Parsing on or more user options failed\n");
299                 goto err;
300         }
301
302         ret = cperf_options_check(&opts);
303         if (ret) {
304                 RTE_LOG(ERR, USER1,
305                                 "Checking on or more user options failed\n");
306                 goto err;
307         }
308
309         if (!opts.silent)
310                 cperf_options_dump(&opts);
311
312         nb_cryptodevs = cperf_initialize_cryptodev(&opts, enabled_cdevs);
313         if (nb_cryptodevs < 1) {
314                 RTE_LOG(ERR, USER1, "Failed to initialise requested crypto "
315                                 "device type\n");
316                 nb_cryptodevs = 0;
317                 goto err;
318         }
319
320         ret = cperf_verify_devices_capabilities(&opts, enabled_cdevs,
321                         nb_cryptodevs);
322         if (ret) {
323                 RTE_LOG(ERR, USER1, "Crypto device type does not support "
324                                 "capabilities requested\n");
325                 goto err;
326         }
327
328         if (opts.test_file != NULL) {
329                 t_vec = cperf_test_vector_get_from_file(&opts);
330                 if (t_vec == NULL) {
331                         RTE_LOG(ERR, USER1,
332                                         "Failed to create test vector for"
333                                         " specified file\n");
334                         goto err;
335                 }
336
337                 if (cperf_check_test_vector(&opts, t_vec)) {
338                         RTE_LOG(ERR, USER1, "Incomplete necessary test vectors"
339                                         "\n");
340                         goto err;
341                 }
342         } else {
343                 t_vec = cperf_test_vector_get_dummy(&opts);
344                 if (t_vec == NULL) {
345                         RTE_LOG(ERR, USER1,
346                                         "Failed to create test vector for"
347                                         " specified algorithms\n");
348                         goto err;
349                 }
350         }
351
352         ret = cperf_get_op_functions(&opts, &op_fns);
353         if (ret) {
354                 RTE_LOG(ERR, USER1, "Failed to find function ops set for "
355                                 "specified algorithms combination\n");
356                 goto err;
357         }
358
359         if (!opts.silent)
360                 show_test_vector(t_vec);
361
362         i = 0;
363         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
364
365                 if (i == nb_cryptodevs)
366                         break;
367
368                 cdev_id = enabled_cdevs[i];
369
370                 ctx[cdev_id] = cperf_testmap[opts.test].constructor(cdev_id, 0,
371                                 &opts, t_vec, &op_fns);
372                 if (ctx[cdev_id] == NULL) {
373                         RTE_LOG(ERR, USER1, "Test run constructor failed\n");
374                         goto err;
375                 }
376                 i++;
377         }
378
379         /* Get first size from range or list */
380         if (opts.inc_buffer_size != 0)
381                 opts.test_buffer_size = opts.min_buffer_size;
382         else
383                 opts.test_buffer_size = opts.buffer_size_list[0];
384
385         while (opts.test_buffer_size <= opts.max_buffer_size) {
386                 i = 0;
387                 RTE_LCORE_FOREACH_SLAVE(lcore_id) {
388
389                         if (i == nb_cryptodevs)
390                                 break;
391
392                         cdev_id = enabled_cdevs[i];
393
394                         rte_eal_remote_launch(cperf_testmap[opts.test].runner,
395                                 ctx[cdev_id], lcore_id);
396                         i++;
397                 }
398                 rte_eal_mp_wait_lcore();
399
400                 /* Get next size from range or list */
401                 if (opts.inc_buffer_size != 0)
402                         opts.test_buffer_size += opts.inc_buffer_size;
403                 else {
404                         if (++buffer_size_idx == opts.buffer_size_count)
405                                 break;
406                         opts.test_buffer_size = opts.buffer_size_list[buffer_size_idx];
407                 }
408         }
409
410         i = 0;
411         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
412
413                 if (i == nb_cryptodevs)
414                         break;
415
416                 cdev_id = enabled_cdevs[i];
417
418                 cperf_testmap[opts.test].destructor(ctx[cdev_id]);
419                 i++;
420         }
421
422         free_test_vector(t_vec, &opts);
423
424         printf("\n");
425         return EXIT_SUCCESS;
426
427 err:
428         i = 0;
429         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
430                 if (i == nb_cryptodevs)
431                         break;
432
433                 cdev_id = enabled_cdevs[i];
434
435                 if (ctx[cdev_id] && cperf_testmap[opts.test].destructor)
436                         cperf_testmap[opts.test].destructor(ctx[cdev_id]);
437                 i++;
438         }
439
440         free_test_vector(t_vec, &opts);
441
442         printf("\n");
443         return EXIT_FAILURE;
444 }