app/crypto-perf: introduce performance test application
[dpdk.git] / app / test-crypto-perf / cperf_verify_parser.c
1 #include <stdio.h>
2
3 #include <rte_malloc.h>
4 #include "cperf_options.h"
5 #include "cperf_test_vectors.h"
6 #include "cperf_verify_parser.h"
7
8 int
9 free_test_vector(struct cperf_test_vector *vector, struct cperf_options *opts)
10 {
11         if (vector == NULL || opts == NULL)
12                 return -1;
13
14         if (opts->test_file == NULL) {
15                 if (vector->iv.data)
16                         rte_free(vector->iv.data);
17                 if (vector->aad.data)
18                         rte_free(vector->aad.data);
19                 if (vector->digest.data)
20                         rte_free(vector->digest.data);
21                 rte_free(vector);
22
23         } else {
24                 if (vector->plaintext.data)
25                         rte_free(vector->plaintext.data);
26                 if (vector->cipher_key.data)
27                         rte_free(vector->cipher_key.data);
28                 if (vector->auth_key.data)
29                         rte_free(vector->auth_key.data);
30                 if (vector->iv.data)
31                         rte_free(vector->iv.data);
32                 if (vector->ciphertext.data)
33                         rte_free(vector->ciphertext.data);
34                 if (vector->aad.data)
35                         rte_free(vector->aad.data);
36                 if (vector->digest.data)
37                         rte_free(vector->digest.data);
38                 rte_free(vector);
39         }
40
41         return 0;
42 }
43
44 /* trim leading and trailing spaces */
45 static char *
46 trim(char *str)
47 {
48         char *start, *end;
49
50         for (start = str; *start; start++) {
51                 if (!isspace((unsigned char) start[0]))
52                         break;
53         }
54
55         for (end = start + strlen(start); end > start + 1; end--) {
56                 if (!isspace((unsigned char) end[-1]))
57                         break;
58         }
59
60         *end = 0;
61
62         /* Shift from "start" to the beginning of the string */
63         if (start > str)
64                 memmove(str, start, (end - start) + 1);
65
66         return str;
67 }
68
69 /* tokenization test values separated by a comma */
70 static int
71 parse_values(char *tokens, uint8_t **data, uint32_t *data_length)
72 {
73         uint8_t n_tokens;
74         uint32_t data_size = 32;
75         uint8_t *values;
76         char *tok, *error = NULL;
77
78         tok = strtok(tokens, VALUE_DELIMITER);
79         if (tok == NULL)
80                 return -1;
81
82         values = (uint8_t *) rte_zmalloc(NULL, sizeof(uint8_t) * data_size, 0);
83         if (values == NULL)
84                 return -1;
85
86         n_tokens = 0;
87         while (tok != NULL) {
88                 uint8_t *values_extended = NULL;
89
90                 if (n_tokens >= data_size) {
91
92                         data_size *= 2;
93
94                         values_extended = (uint8_t *) rte_realloc(values,
95                                 sizeof(uint8_t) * data_size, 0);
96                         if (values_extended == NULL) {
97                                 rte_free(values);
98                                 return -1;
99                         }
100
101                         values = values_extended;
102                 }
103
104                 values[n_tokens] = (uint8_t) strtoul(tok, &error, 0);
105                 if ((error == NULL) || (*error != '\0')) {
106                         printf("Failed with convert '%s'\n", tok);
107                         rte_free(values);
108                         return -1;
109                 }
110
111                 tok = strtok(NULL, VALUE_DELIMITER);
112                 if (tok == NULL)
113                         break;
114
115                 n_tokens++;
116         }
117
118         uint8_t *resize_values = (uint8_t *) rte_realloc(values,
119                 sizeof(uint8_t) * (n_tokens + 1), 0);
120
121         if (resize_values == NULL) {
122                 rte_free(values);
123                 return -1;
124         }
125
126         *data = resize_values;
127         *data_length = n_tokens + 1;
128
129         return 0;
130 }
131
132 /* checks the type of key and assigns data */
133 static int
134 parse_entry(char *entry, struct cperf_test_vector *vector)
135 {
136         char *token, *key_token;
137         uint8_t *data = NULL;
138         int status;
139         uint32_t data_length;
140
141         /* get key */
142         token = strtok(entry, ENTRY_DELIMITER);
143         key_token = token;
144
145         /* get values for key */
146         token = strtok(NULL, ENTRY_DELIMITER);
147
148         if (token == NULL) {
149                 printf("Expected 'key = values' but was '%.40s'..\n",
150                         key_token);
151                 return -1;
152         }
153
154         status = parse_values(token, &data, &data_length);
155         if (status)
156                 return -1;
157
158         /* compare keys */
159         if (strstr(key_token, "plaintext")) {
160                 if (vector->plaintext.data)
161                         rte_free(vector->plaintext.data);
162                 vector->plaintext.data = data;
163                 vector->plaintext.length = data_length;
164         } else if (strstr(key_token, "cipher_key")) {
165                 if (vector->cipher_key.data)
166                         rte_free(vector->cipher_key.data);
167                 vector->cipher_key.data = data;
168                 vector->cipher_key.length = data_length;
169         } else if (strstr(key_token, "auth_key")) {
170                 if (vector->auth_key.data)
171                         rte_free(vector->auth_key.data);
172                 vector->auth_key.data = data;
173                 vector->auth_key.length = data_length;
174         } else if (strstr(key_token, "iv")) {
175                 if (vector->iv.data)
176                         rte_free(vector->iv.data);
177                 vector->iv.data = data;
178                 vector->iv.phys_addr = rte_malloc_virt2phy(vector->iv.data);
179                 vector->iv.length = data_length;
180         } else if (strstr(key_token, "ciphertext")) {
181                 if (vector->ciphertext.data)
182                         rte_free(vector->ciphertext.data);
183                 vector->ciphertext.data = data;
184                 vector->ciphertext.length = data_length;
185         } else if (strstr(key_token, "aad")) {
186                 if (vector->aad.data)
187                         rte_free(vector->aad.data);
188                 vector->aad.data = data;
189                 vector->aad.phys_addr = rte_malloc_virt2phy(vector->aad.data);
190                 vector->aad.length = data_length;
191         } else if (strstr(key_token, "digest")) {
192                 if (vector->digest.data)
193                         rte_free(vector->digest.data);
194                 vector->digest.data = data;
195                 vector->digest.phys_addr = rte_malloc_virt2phy(
196                         vector->digest.data);
197                 vector->digest.length = data_length;
198         } else {
199                 printf("Not valid key: '%s'\n", trim(key_token));
200                 return -1;
201         }
202
203         return 0;
204 }
205
206 /* searches in the file for registry keys and values */
207 static int
208 parse_file(struct cperf_test_vector *v_vec, const char *path)
209 {
210         FILE *fp;
211         char *line = NULL, *entry = NULL;
212         ssize_t read;
213         size_t len = 0;
214         int status = 0;
215
216         fp = fopen(path, "r");
217         if (fp == NULL) {
218                 printf("File %s does not exists\n", path);
219                 return -1;
220         }
221
222         while ((read = getline(&line, &len, fp)) != -1) {
223                 /* ignore comments and new lines */
224                 if (line[0] == '#' || line[0] == '/' || line[0] == '\n'
225                         || line[0] == '\r' || line[0] == ' ')
226                         continue;
227
228                 trim(line);
229
230                 /* buffer for multiline */
231                 entry = (char *) rte_realloc(entry,
232                                         sizeof(char) * strlen(line) + 1, 0);
233                 if (entry == NULL)
234                         return -1;
235
236                 memset(entry, 0, strlen(line) + 1);
237                 strncpy(entry, line, strlen(line));
238
239                 /* check if entry ends with , or = */
240                 if (entry[strlen(entry) - 1] == ','
241                         || entry[strlen(entry) - 1] == '=') {
242                         while ((read = getline(&line, &len, fp)) != -1) {
243                                 trim(line);
244
245                                 /* extend entry about length of new line */
246                                 char *entry_extended = (char *) rte_realloc(
247                                         entry, sizeof(char)
248                                                 * (strlen(line) + strlen(entry))
249                                                 + 1, 0);
250
251                                 if (entry_extended == NULL)
252                                         goto err;
253                                 entry = entry_extended;
254
255                                 strncat(entry, line, strlen(line));
256
257                                 if (entry[strlen(entry) - 1] != ',')
258                                         break;
259                         }
260                 }
261                 status = parse_entry(entry, v_vec);
262                 if (status) {
263                         printf("An error occurred while parsing!\n");
264                         goto err;
265                 }
266         }
267
268         fclose(fp);
269         free(line);
270         rte_free(entry);
271
272         return 0;
273
274 err:
275         if (fp)
276                 fclose(fp);
277         if (line)
278                 free(line);
279         if (entry)
280                 rte_free(entry);
281
282         return -1;
283 }
284
285 struct cperf_test_vector*
286 cperf_test_vector_get_from_file(struct cperf_options *opts)
287 {
288         int status;
289         struct cperf_test_vector *test_vector = NULL;
290
291         if (opts == NULL || opts->test_file == NULL)
292                 return test_vector;
293
294         test_vector = (struct cperf_test_vector *) rte_zmalloc(NULL,
295                 sizeof(struct cperf_test_vector), 0);
296         if (test_vector == NULL)
297                 return test_vector;
298
299         /* filling the vector with data from a file */
300         status = parse_file(test_vector, opts->test_file);
301         if (status) {
302                 free_test_vector(test_vector, opts);
303                 return NULL;
304         }
305
306         /* other values not included in the file */
307         test_vector->data.cipher_offset = 0;
308         test_vector->data.cipher_length = opts->buffer_sz;
309
310         test_vector->data.auth_offset = 0;
311         test_vector->data.auth_length = opts->buffer_sz;
312
313         return test_vector;
314 }