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