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