app/crypto-perf: introduce performance test application
[dpdk.git] / app / test-crypto-perf / cperf_test_vector_parsing.c
1 #include <stdio.h>
2
3 #include <rte_malloc.h>
4
5 #include "cperf_options.h"
6 #include "cperf_test_vectors.h"
7 #include "cperf_test_vector_parsing.h"
8
9 int
10 free_test_vector(struct cperf_test_vector *vector, struct cperf_options *opts)
11 {
12         if (vector == NULL || opts == NULL)
13                 return -1;
14
15         rte_free(vector->iv.data);
16         rte_free(vector->aad.data);
17         rte_free(vector->digest.data);
18
19         if (opts->test_file != NULL) {
20                 rte_free(vector->plaintext.data);
21                 rte_free(vector->cipher_key.data);
22                 rte_free(vector->auth_key.data);
23                 rte_free(vector->ciphertext.data);
24         }
25
26         rte_free(vector);
27
28         return 0;
29 }
30
31 void
32 show_test_vector(struct cperf_test_vector *test_vector)
33 {
34         const uint8_t wrap = 32;
35         uint32_t i;
36
37         if (test_vector == NULL)
38                 return;
39
40         if (test_vector->plaintext.data) {
41                 printf("\nplaintext =\n");
42                 for (i = 0; i < test_vector->plaintext.length; ++i) {
43                         if ((i % wrap == 0) && (i != 0))
44                                 printf("\n");
45                         if (i == test_vector->plaintext.length - 1)
46                                 printf("0x%02x",
47                                         test_vector->plaintext.data[i]);
48                         else
49                                 printf("0x%02x, ",
50                                         test_vector->plaintext.data[i]);
51                 }
52                 printf("\n");
53         }
54
55         if (test_vector->cipher_key.data) {
56                 printf("\ncipher_key =\n");
57                 for (i = 0; i < test_vector->cipher_key.length; ++i) {
58                         if ((i % wrap == 0) && (i != 0))
59                                 printf("\n");
60                         if (i == (uint32_t)(test_vector->cipher_key.length - 1))
61                                 printf("0x%02x",
62                                         test_vector->cipher_key.data[i]);
63                         else
64                                 printf("0x%02x, ",
65                                         test_vector->cipher_key.data[i]);
66                 }
67                 printf("\n");
68         }
69
70         if (test_vector->auth_key.data) {
71                 printf("\nauth_key =\n");
72                 for (i = 0; i < test_vector->auth_key.length; ++i) {
73                         if ((i % wrap == 0) && (i != 0))
74                                 printf("\n");
75                         if (i == (uint32_t)(test_vector->auth_key.length - 1))
76                                 printf("0x%02x", test_vector->auth_key.data[i]);
77                         else
78                                 printf("0x%02x, ",
79                                         test_vector->auth_key.data[i]);
80                 }
81                 printf("\n");
82         }
83
84         if (test_vector->iv.data) {
85                 printf("\niv =\n");
86                 for (i = 0; i < test_vector->iv.length; ++i) {
87                         if ((i % wrap == 0) && (i != 0))
88                                 printf("\n");
89                         if (i == (uint32_t)(test_vector->iv.length - 1))
90                                 printf("0x%02x", test_vector->iv.data[i]);
91                         else
92                                 printf("0x%02x, ", test_vector->iv.data[i]);
93                 }
94                 printf("\n");
95         }
96
97         if (test_vector->ciphertext.data) {
98                 printf("\nciphertext =\n");
99                 for (i = 0; i < test_vector->ciphertext.length; ++i) {
100                         if ((i % wrap == 0) && (i != 0))
101                                 printf("\n");
102                         if (i == test_vector->ciphertext.length - 1)
103                                 printf("0x%02x",
104                                         test_vector->ciphertext.data[i]);
105                         else
106                                 printf("0x%02x, ",
107                                         test_vector->ciphertext.data[i]);
108                 }
109                 printf("\n");
110         }
111
112         if (test_vector->aad.data) {
113                 printf("\naad =\n");
114                 for (i = 0; i < test_vector->aad.length; ++i) {
115                         if ((i % wrap == 0) && (i != 0))
116                                 printf("\n");
117                         if (i == (uint32_t)(test_vector->aad.length - 1))
118                                 printf("0x%02x", test_vector->aad.data[i]);
119                         else
120                                 printf("0x%02x, ", test_vector->aad.data[i]);
121                 }
122                 printf("\n");
123         }
124
125         if (test_vector->digest.data) {
126                 printf("\ndigest =\n");
127                 for (i = 0; i < test_vector->digest.length; ++i) {
128                         if ((i % wrap == 0) && (i != 0))
129                                 printf("\n");
130                         if (i == (uint32_t)(test_vector->digest.length - 1))
131                                 printf("0x%02x", test_vector->digest.data[i]);
132                         else
133                                 printf("0x%02x, ", test_vector->digest.data[i]);
134                 }
135                 printf("\n");
136         }
137 }
138
139 /* trim leading and trailing spaces */
140 static char *
141 trim_space(char *str)
142 {
143         char *start, *end;
144
145         for (start = str; *start; start++) {
146                 if (!isspace((unsigned char) start[0]))
147                         break;
148         }
149
150         for (end = start + strlen(start); end > start + 1; end--) {
151                 if (!isspace((unsigned char) end[-1]))
152                         break;
153         }
154
155         *end = 0;
156
157         /* Shift from "start" to the beginning of the string */
158         if (start > str)
159                 memmove(str, start, (end - start) + 1);
160
161         return str;
162 }
163
164 /* tokenization test values separated by a comma */
165 static int
166 parse_values(char *tokens, uint8_t **data, uint32_t *data_length)
167 {
168         uint32_t n_tokens;
169         uint32_t data_size = 32;
170
171         uint8_t *values, *values_resized;
172         char *tok, *error = NULL;
173
174         tok = strtok(tokens, CPERF_VALUE_DELIMITER);
175         if (tok == NULL)
176                 return -1;
177
178         values = (uint8_t *) rte_zmalloc(NULL, sizeof(uint8_t) * data_size, 0);
179         if (values == NULL)
180                 return -1;
181
182         n_tokens = 0;
183         while (tok != NULL) {
184                 values_resized = NULL;
185
186                 if (n_tokens >= data_size) {
187                         data_size *= 2;
188
189                         values_resized = (uint8_t *) rte_realloc(values,
190                                 sizeof(uint8_t) * data_size, 0);
191                         if (values_resized == NULL) {
192                                 rte_free(values);
193                                 return -1;
194                         }
195                         values = values_resized;
196                 }
197
198                 values[n_tokens] = (uint8_t) strtoul(tok, &error, 0);
199                 if ((error == NULL) || (*error != '\0')) {
200                         printf("Failed with convert '%s'\n", tok);
201                         rte_free(values);
202                         return -1;
203                 }
204
205                 tok = strtok(NULL, CPERF_VALUE_DELIMITER);
206                 if (tok == NULL)
207                         break;
208
209                 n_tokens++;
210         }
211
212         values_resized = (uint8_t *) rte_realloc(values,
213                 sizeof(uint8_t) * (n_tokens + 1), 0);
214
215         if (values_resized == NULL) {
216                 rte_free(values);
217                 return -1;
218         }
219
220         *data = values_resized;
221         *data_length = n_tokens + 1;
222
223         return 0;
224 }
225
226 /* checks the type of key and assigns data */
227 static int
228 parse_entry(char *entry, struct cperf_test_vector *vector,
229         struct cperf_options *opts, uint8_t tc_found)
230 {
231         int status;
232         uint32_t data_length;
233
234         uint8_t *data = NULL;
235         char *token, *key_token;
236
237         /* get key */
238         token = strtok(entry, CPERF_ENTRY_DELIMITER);
239         key_token = token;
240
241         /* get values for key */
242         token = strtok(NULL, CPERF_ENTRY_DELIMITER);
243         if (token == NULL) {
244                 printf("Expected 'key = values' but was '%.40s'..\n",
245                         key_token);
246                 return -1;
247         }
248
249         status = parse_values(token, &data, &data_length);
250         if (status)
251                 return -1;
252
253         /* compare keys */
254         if (strstr(key_token, "plaintext")) {
255                 rte_free(vector->plaintext.data);
256                 vector->plaintext.data = data;
257                 if (tc_found)
258                         vector->plaintext.length = data_length;
259                 else {
260                         if (opts->buffer_sz > data_length) {
261                                 printf("Global plaintext shorter than "
262                                         "buffer_sz\n");
263                                 return -1;
264                         }
265                         vector->plaintext.length = opts->buffer_sz;
266                 }
267
268         } else if (strstr(key_token, "cipher_key")) {
269                 rte_free(vector->cipher_key.data);
270                 vector->cipher_key.data = data;
271                 if (tc_found)
272                         vector->cipher_key.length = data_length;
273                 else {
274                         if (opts->cipher_key_sz > data_length) {
275                                 printf("Global cipher_key shorter than "
276                                         "cipher_key_sz\n");
277                                 return -1;
278                         }
279                         vector->cipher_key.length = opts->cipher_key_sz;
280                 }
281
282         } else if (strstr(key_token, "auth_key")) {
283                 rte_free(vector->auth_key.data);
284                 vector->auth_key.data = data;
285                 if (tc_found)
286                         vector->auth_key.length = data_length;
287                 else {
288                         if (opts->auth_key_sz > data_length) {
289                                 printf("Global auth_key shorter than "
290                                         "auth_key_sz\n");
291                                 return -1;
292                         }
293                         vector->auth_key.length = opts->auth_key_sz;
294                 }
295
296         } else if (strstr(key_token, "iv")) {
297                 rte_free(vector->iv.data);
298                 vector->iv.data = data;
299                 vector->iv.phys_addr = rte_malloc_virt2phy(vector->iv.data);
300                 if (tc_found)
301                         vector->iv.length = data_length;
302                 else {
303                         if (opts->cipher_iv_sz > data_length) {
304                                 printf("Global iv shorter than "
305                                         "cipher_iv_sz\n");
306                                 return -1;
307                         }
308                         vector->iv.length = opts->cipher_iv_sz;
309                 }
310
311         } else if (strstr(key_token, "ciphertext")) {
312                 rte_free(vector->ciphertext.data);
313                 vector->ciphertext.data = data;
314                 if (tc_found)
315                         vector->ciphertext.length = data_length;
316                 else {
317                         if (opts->buffer_sz > data_length) {
318                                 printf("Global ciphertext shorter than "
319                                         "buffer_sz\n");
320                                 return -1;
321                         }
322                         vector->ciphertext.length = opts->buffer_sz;
323                 }
324
325         } else if (strstr(key_token, "aad")) {
326                 rte_free(vector->aad.data);
327                 vector->aad.data = data;
328                 vector->aad.phys_addr = rte_malloc_virt2phy(vector->aad.data);
329                 if (tc_found)
330                         vector->aad.length = data_length;
331                 else {
332                         if (opts->auth_aad_sz > data_length) {
333                                 printf("Global aad shorter than "
334                                         "auth_aad_sz\n");
335                                 return -1;
336                         }
337                         vector->aad.length = opts->auth_aad_sz;
338                 }
339
340         } else if (strstr(key_token, "digest")) {
341                 rte_free(vector->digest.data);
342                 vector->digest.data = data;
343                 vector->digest.phys_addr = rte_malloc_virt2phy(
344                         vector->digest.data);
345                 if (tc_found)
346                         vector->digest.length = data_length;
347                 else {
348                         if (opts->auth_digest_sz > data_length) {
349                                 printf("Global digest shorter than "
350                                         "auth_digest_sz\n");
351                                 return -1;
352                         }
353                         vector->digest.length = opts->auth_digest_sz;
354                 }
355         } else {
356                 printf("Not valid key: '%s'\n", trim_space(key_token));
357                 return -1;
358         }
359
360         return 0;
361 }
362
363 /* searches in the file for test keys and values */
364 static int
365 parse_file(struct cperf_test_vector *vector, struct cperf_options *opts)
366 {
367         uint8_t tc_found = 0;
368         uint8_t tc_data_start = 0;
369         ssize_t read;
370         size_t len = 0;
371         int status = 0;
372
373         FILE *fp;
374         char *line = NULL;
375         char *entry = NULL;
376
377         fp = fopen(opts->test_file, "r");
378         if (fp == NULL) {
379                 printf("File %s does not exists\n", opts->test_file);
380                 return -1;
381         }
382
383         while ((read = getline(&line, &len, fp)) != -1) {
384
385                 /* ignore comments and new lines */
386                 if (line[0] == '#' || line[0] == '/' || line[0] == '\n'
387                         || line[0] == '\r' || line[0] == ' ')
388                         continue;
389
390                 trim_space(line);
391
392                 /* next test case is started */
393                 if (line[0] == '[' && line[strlen(line) - 1] == ']' && tc_found)
394                         break;
395                 /* test case section started, end of global data */
396                 else if (line[0] == '[' && line[strlen(line) - 1] == ']')
397                         tc_data_start = 1;
398
399                 /* test name unspecified, end after global data */
400                 if (tc_data_start && opts->test_name == NULL)
401                         break;
402                 /* searching for a suitable test */
403                 else if (tc_data_start && tc_found == 0) {
404                         if (!strcmp(line, opts->test_name)) {
405                                 tc_found = 1;
406                                 continue;
407                         } else
408                                 continue;
409                 }
410
411                 /* buffer for multiline */
412                 entry = (char *) rte_realloc(entry,
413                                         sizeof(char) * strlen(line) + 1, 0);
414                 if (entry == NULL)
415                         return -1;
416
417                 memset(entry, 0, strlen(line) + 1);
418                 strncpy(entry, line, strlen(line));
419
420                 /* check if entry ends with , or = */
421                 if (entry[strlen(entry) - 1] == ','
422                         || entry[strlen(entry) - 1] == '=') {
423                         while ((read = getline(&line, &len, fp)) != -1) {
424                                 trim_space(line);
425
426                                 /* extend entry about length of new line */
427                                 char *entry_extended = (char *) rte_realloc(
428                                         entry, sizeof(char)
429                                                 * (strlen(line) + strlen(entry))
430                                                 + 1, 0);
431
432                                 if (entry_extended == NULL)
433                                         goto err;
434                                 entry = entry_extended;
435
436                                 strncat(entry, line, strlen(line));
437
438                                 if (entry[strlen(entry) - 1] != ',')
439                                         break;
440                         }
441                 }
442                 status = parse_entry(entry, vector, opts, tc_found);
443                 if (status) {
444                         printf("An error occurred while parsing!\n");
445                         goto err;
446                 }
447         }
448
449         if (tc_found == 0 && opts->test_name != NULL) {
450                 printf("Not found '%s' case in test file\n", opts->test_name);
451                 goto err;
452         }
453
454         fclose(fp);
455         free(line);
456         rte_free(entry);
457
458         return 0;
459
460 err:
461         if (fp)
462                 fclose(fp);
463         if (line)
464                 free(line);
465         if (entry)
466                 rte_free(entry);
467
468         return -1;
469 }
470
471 struct cperf_test_vector*
472 cperf_test_vector_get_from_file(struct cperf_options *opts)
473 {
474         int status;
475         struct cperf_test_vector *test_vector = NULL;
476
477         if (opts == NULL || opts->test_file == NULL)
478                 return test_vector;
479
480         test_vector = (struct cperf_test_vector *) rte_zmalloc(NULL,
481                 sizeof(struct cperf_test_vector), 0);
482         if (test_vector == NULL)
483                 return test_vector;
484
485         /* filling the vector with data from a file */
486         status = parse_file(test_vector, opts);
487         if (status) {
488                 free_test_vector(test_vector, opts);
489                 return NULL;
490         }
491
492         /* other values not included in the file */
493         test_vector->data.cipher_offset = 0;
494         test_vector->data.cipher_length = opts->buffer_sz;
495
496         test_vector->data.auth_offset = 0;
497         test_vector->data.auth_length = opts->buffer_sz;
498
499         return test_vector;
500 }