1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2020 Intel Corporation 3 */ 4 #include <stdint.h> 5 #include <inttypes.h> 6 #include <stdlib.h> 7 #include <stdio.h> 8 #include <string.h> 9 #include <errno.h> 10 11 #include <rte_common.h> 12 #include <rte_mempool.h> 13 14 #include <rte_swx_port_ethdev.h> 15 #include <rte_swx_port_ring.h> 16 #include <rte_swx_port_source_sink.h> 17 #include <rte_swx_port_fd.h> 18 19 #include "rte_swx_pipeline_spec.h" 20 21 #ifndef MAX_LINE_LENGTH 22 #define MAX_LINE_LENGTH 2048 23 #endif 24 25 #ifndef MAX_TOKENS 26 #define MAX_TOKENS 256 27 #endif 28 29 #define STRUCT_BLOCK 0 30 #define ACTION_BLOCK 1 31 #define TABLE_BLOCK 2 32 #define TABLE_KEY_BLOCK 3 33 #define TABLE_ACTIONS_BLOCK 4 34 #define SELECTOR_BLOCK 5 35 #define SELECTOR_SELECTOR_BLOCK 6 36 #define LEARNER_BLOCK 7 37 #define LEARNER_KEY_BLOCK 8 38 #define LEARNER_ACTIONS_BLOCK 9 39 #define LEARNER_TIMEOUT_BLOCK 10 40 #define APPLY_BLOCK 11 41 42 /* 43 * extobj. 44 */ 45 static void 46 extobj_spec_free(struct extobj_spec *s) 47 { 48 if (!s) 49 return; 50 51 free(s->name); 52 s->name = NULL; 53 54 free(s->extern_type_name); 55 s->extern_type_name = NULL; 56 57 free(s->pragma); 58 s->pragma = NULL; 59 } 60 61 static int 62 extobj_statement_parse(struct extobj_spec *s, 63 char **tokens, 64 uint32_t n_tokens, 65 uint32_t n_lines, 66 uint32_t *err_line, 67 const char **err_msg) 68 { 69 /* Check format. */ 70 if (((n_tokens != 4) && (n_tokens != 6)) || 71 ((n_tokens == 4) && strcmp(tokens[2], "instanceof")) || 72 ((n_tokens == 6) && (strcmp(tokens[2], "instanceof") || 73 strcmp(tokens[4], "pragma")))) { 74 if (err_line) 75 *err_line = n_lines; 76 if (err_msg) 77 *err_msg = "Invalid extobj statement."; 78 return -EINVAL; 79 } 80 81 /* spec. */ 82 s->name = strdup(tokens[1]); 83 s->extern_type_name = strdup(tokens[3]); 84 s->pragma = (n_tokens == 6) ? strdup(tokens[5]) : NULL; 85 86 if (!s->name || 87 !s->extern_type_name || 88 ((n_tokens == 6) && !s->pragma)) { 89 free(s->name); 90 free(s->extern_type_name); 91 free(s->pragma); 92 93 if (err_line) 94 *err_line = n_lines; 95 if (err_msg) 96 *err_msg = "Memory allocation failed."; 97 return -ENOMEM; 98 } 99 100 return 0; 101 } 102 103 /* 104 * struct. 105 */ 106 static void 107 struct_spec_free(struct struct_spec *s) 108 { 109 uint32_t i; 110 111 if (!s) 112 return; 113 114 free(s->name); 115 s->name = NULL; 116 117 for (i = 0; i < s->n_fields; i++) { 118 uintptr_t name = (uintptr_t)s->fields[i].name; 119 120 free((void *)name); 121 } 122 123 free(s->fields); 124 s->fields = NULL; 125 126 s->n_fields = 0; 127 128 s->varbit = 0; 129 } 130 131 static int 132 struct_statement_parse(struct struct_spec *s, 133 uint32_t *block_mask, 134 char **tokens, 135 uint32_t n_tokens, 136 uint32_t n_lines, 137 uint32_t *err_line, 138 const char **err_msg) 139 { 140 /* Check format. */ 141 if ((n_tokens != 3) || strcmp(tokens[2], "{")) { 142 if (err_line) 143 *err_line = n_lines; 144 if (err_msg) 145 *err_msg = "Invalid struct statement."; 146 return -EINVAL; 147 } 148 149 /* spec. */ 150 s->name = strdup(tokens[1]); 151 if (!s->name) { 152 if (err_line) 153 *err_line = n_lines; 154 if (err_msg) 155 *err_msg = "Memory allocation failed."; 156 return -ENOMEM; 157 } 158 159 /* block_mask. */ 160 *block_mask |= 1 << STRUCT_BLOCK; 161 162 return 0; 163 } 164 165 static int 166 struct_block_parse(struct struct_spec *s, 167 uint32_t *block_mask, 168 char **tokens, 169 uint32_t n_tokens, 170 uint32_t n_lines, 171 uint32_t *err_line, 172 const char **err_msg) 173 { 174 struct rte_swx_field_params *new_fields; 175 char *p = tokens[0], *name = NULL; 176 uint32_t n_bits; 177 int varbit = 0, error = 0, error_size_invalid = 0, error_varbit_not_last = 0; 178 179 /* Handle end of block. */ 180 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 181 *block_mask &= ~(1 << STRUCT_BLOCK); 182 return 0; 183 } 184 185 /* Check format. */ 186 if (n_tokens != 2) { 187 error = -EINVAL; 188 goto error; 189 } 190 191 if (s->varbit) { 192 error = -EINVAL; 193 error_varbit_not_last = 1; 194 goto error; 195 } 196 197 if (!strncmp(p, "bit<", strlen("bit<"))) { 198 size_t len = strlen(p); 199 200 if ((len < strlen("bit< >")) || (p[len - 1] != '>')) { 201 error = -EINVAL; 202 goto error; 203 } 204 205 /* Remove the "bit<" and ">". */ 206 p[strlen(p) - 1] = 0; 207 p += strlen("bit<"); 208 } else if (!strncmp(p, "varbit<", strlen("varbit<"))) { 209 size_t len = strlen(p); 210 211 if ((len < strlen("varbit< >")) || (p[len - 1] != '>')) { 212 error = -EINVAL; 213 goto error; 214 } 215 216 /* Remove the "varbit<" and ">". */ 217 p[strlen(p) - 1] = 0; 218 p += strlen("varbit<"); 219 220 /* Set the varbit flag. */ 221 varbit = 1; 222 } else { 223 error = -EINVAL; 224 goto error; 225 } 226 227 n_bits = strtoul(p, &p, 0); 228 if ((p[0]) || 229 !n_bits || 230 (n_bits % 8)) { 231 error = -EINVAL; 232 error_size_invalid = 1; 233 goto error; 234 } 235 236 /* spec. */ 237 name = strdup(tokens[1]); 238 if (!name) { 239 error = -ENOMEM; 240 goto error; 241 } 242 243 new_fields = realloc(s->fields, (s->n_fields + 1) * sizeof(struct rte_swx_field_params)); 244 if (!new_fields) { 245 error = -ENOMEM; 246 goto error; 247 } 248 249 s->fields = new_fields; 250 s->fields[s->n_fields].name = name; 251 s->fields[s->n_fields].n_bits = n_bits; 252 s->n_fields++; 253 s->varbit = varbit; 254 255 return 0; 256 257 error: 258 free(name); 259 260 if (err_line) 261 *err_line = n_lines; 262 263 if (err_msg) { 264 *err_msg = "Invalid struct field statement."; 265 266 if ((error == -EINVAL) && error_varbit_not_last) 267 *err_msg = "Varbit field is not the last struct field."; 268 269 if ((error == -EINVAL) && error_size_invalid) 270 *err_msg = "Invalid struct field size."; 271 272 if (error == -ENOMEM) 273 *err_msg = "Memory allocation failed."; 274 } 275 276 return error; 277 } 278 279 /* 280 * header. 281 */ 282 static void 283 header_spec_free(struct header_spec *s) 284 { 285 if (!s) 286 return; 287 288 free(s->name); 289 s->name = NULL; 290 291 free(s->struct_type_name); 292 s->struct_type_name = NULL; 293 } 294 295 static int 296 header_statement_parse(struct header_spec *s, 297 char **tokens, 298 uint32_t n_tokens, 299 uint32_t n_lines, 300 uint32_t *err_line, 301 const char **err_msg) 302 { 303 /* Check format. */ 304 if ((n_tokens != 4) || strcmp(tokens[2], "instanceof")) { 305 if (err_line) 306 *err_line = n_lines; 307 if (err_msg) 308 *err_msg = "Invalid header statement."; 309 return -EINVAL; 310 } 311 312 /* spec. */ 313 s->name = strdup(tokens[1]); 314 s->struct_type_name = strdup(tokens[3]); 315 316 if (!s->name || !s->struct_type_name) { 317 free(s->name); 318 free(s->struct_type_name); 319 320 if (err_line) 321 *err_line = n_lines; 322 if (err_msg) 323 *err_msg = "Memory allocation failed."; 324 return -ENOMEM; 325 } 326 327 return 0; 328 } 329 330 /* 331 * metadata. 332 */ 333 static void 334 metadata_spec_free(struct metadata_spec *s) 335 { 336 if (!s) 337 return; 338 339 free(s->struct_type_name); 340 s->struct_type_name = NULL; 341 } 342 343 static int 344 metadata_statement_parse(struct metadata_spec *s, 345 char **tokens, 346 uint32_t n_tokens, 347 uint32_t n_lines, 348 uint32_t *err_line, 349 const char **err_msg) 350 { 351 /* Check format. */ 352 if ((n_tokens != 3) || strcmp(tokens[1], "instanceof")) { 353 if (err_line) 354 *err_line = n_lines; 355 if (err_msg) 356 *err_msg = "Invalid metadata statement."; 357 return -EINVAL; 358 } 359 360 /* spec. */ 361 s->struct_type_name = strdup(tokens[2]); 362 if (!s->struct_type_name) { 363 if (err_line) 364 *err_line = n_lines; 365 if (err_msg) 366 *err_msg = "Memory allocation failed."; 367 return -ENOMEM; 368 } 369 370 return 0; 371 } 372 373 /* 374 * action. 375 */ 376 static void 377 action_spec_free(struct action_spec *s) 378 { 379 uint32_t i; 380 381 if (!s) 382 return; 383 384 free(s->name); 385 s->name = NULL; 386 387 free(s->args_struct_type_name); 388 s->args_struct_type_name = NULL; 389 390 for (i = 0; i < s->n_instructions; i++) { 391 uintptr_t instr = (uintptr_t)s->instructions[i]; 392 393 free((void *)instr); 394 } 395 396 free(s->instructions); 397 s->instructions = NULL; 398 399 s->n_instructions = 0; 400 } 401 402 static int 403 action_statement_parse(struct action_spec *s, 404 uint32_t *block_mask, 405 char **tokens, 406 uint32_t n_tokens, 407 uint32_t n_lines, 408 uint32_t *err_line, 409 const char **err_msg) 410 { 411 /* Check format. */ 412 if (((n_tokens != 5) && (n_tokens != 6)) || 413 ((n_tokens == 5) && 414 (strcmp(tokens[2], "args") || 415 strcmp(tokens[3], "none") || 416 strcmp(tokens[4], "{"))) || 417 ((n_tokens == 6) && 418 (strcmp(tokens[2], "args") || 419 strcmp(tokens[3], "instanceof") || 420 strcmp(tokens[5], "{")))) { 421 if (err_line) 422 *err_line = n_lines; 423 if (err_msg) 424 *err_msg = "Invalid action statement."; 425 return -EINVAL; 426 } 427 428 /* spec. */ 429 s->name = strdup(tokens[1]); 430 s->args_struct_type_name = (n_tokens == 6) ? strdup(tokens[4]) : NULL; 431 432 if ((!s->name) || ((n_tokens == 6) && !s->args_struct_type_name)) { 433 if (err_line) 434 *err_line = n_lines; 435 if (err_msg) 436 *err_msg = "Memory allocation failed."; 437 return -ENOMEM; 438 } 439 440 /* block_mask. */ 441 *block_mask |= 1 << ACTION_BLOCK; 442 443 return 0; 444 } 445 446 static int 447 action_block_parse(struct action_spec *s, 448 uint32_t *block_mask, 449 char **tokens, 450 uint32_t n_tokens, 451 uint32_t n_lines, 452 uint32_t *err_line, 453 const char **err_msg) 454 { 455 char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr; 456 const char **new_instructions; 457 uint32_t i; 458 459 /* Handle end of block. */ 460 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 461 *block_mask &= ~(1 << ACTION_BLOCK); 462 return 0; 463 } 464 465 /* spec. */ 466 buffer[0] = 0; 467 for (i = 0; i < n_tokens; i++) { 468 if (i) 469 strcat(buffer, " "); 470 strcat(buffer, tokens[i]); 471 } 472 473 instr = strdup(buffer); 474 if (!instr) { 475 if (err_line) 476 *err_line = n_lines; 477 if (err_msg) 478 *err_msg = "Memory allocation failed."; 479 return -ENOMEM; 480 } 481 482 new_instructions = realloc(s->instructions, 483 (s->n_instructions + 1) * sizeof(char *)); 484 if (!new_instructions) { 485 free(instr); 486 487 if (err_line) 488 *err_line = n_lines; 489 if (err_msg) 490 *err_msg = "Memory allocation failed."; 491 return -ENOMEM; 492 } 493 494 s->instructions = new_instructions; 495 s->instructions[s->n_instructions] = instr; 496 s->n_instructions++; 497 498 return 0; 499 } 500 501 /* 502 * table. 503 */ 504 static void 505 table_spec_free(struct table_spec *s) 506 { 507 uintptr_t default_action_name, default_action_args, hash_func_name; 508 uint32_t i; 509 510 if (!s) 511 return; 512 513 free(s->name); 514 s->name = NULL; 515 516 for (i = 0; i < s->params.n_fields; i++) { 517 uintptr_t name = (uintptr_t)s->params.fields[i].name; 518 519 free((void *)name); 520 } 521 522 free(s->params.fields); 523 s->params.fields = NULL; 524 525 s->params.n_fields = 0; 526 527 for (i = 0; i < s->params.n_actions; i++) { 528 uintptr_t name = (uintptr_t)s->params.action_names[i]; 529 530 free((void *)name); 531 } 532 533 free(s->params.action_names); 534 s->params.action_names = NULL; 535 536 s->params.n_actions = 0; 537 538 default_action_name = (uintptr_t)s->params.default_action_name; 539 free((void *)default_action_name); 540 s->params.default_action_name = NULL; 541 542 default_action_args = (uintptr_t)s->params.default_action_args; 543 free((void *)default_action_args); 544 s->params.default_action_args = NULL; 545 546 free(s->params.action_is_for_table_entries); 547 s->params.action_is_for_table_entries = NULL; 548 549 free(s->params.action_is_for_default_entry); 550 s->params.action_is_for_default_entry = NULL; 551 552 s->params.default_action_is_const = 0; 553 554 hash_func_name = (uintptr_t)s->params.hash_func_name; 555 free((void *)hash_func_name); 556 s->params.hash_func_name = NULL; 557 558 free(s->recommended_table_type_name); 559 s->recommended_table_type_name = NULL; 560 561 free(s->args); 562 s->args = NULL; 563 564 s->size = 0; 565 } 566 567 static int 568 table_key_statement_parse(uint32_t *block_mask, 569 char **tokens, 570 uint32_t n_tokens, 571 uint32_t n_lines, 572 uint32_t *err_line, 573 const char **err_msg) 574 { 575 /* Check format. */ 576 if ((n_tokens != 2) || strcmp(tokens[1], "{")) { 577 if (err_line) 578 *err_line = n_lines; 579 if (err_msg) 580 *err_msg = "Invalid key statement."; 581 return -EINVAL; 582 } 583 584 /* block_mask. */ 585 *block_mask |= 1 << TABLE_KEY_BLOCK; 586 587 return 0; 588 } 589 590 static int 591 table_key_block_parse(struct table_spec *s, 592 uint32_t *block_mask, 593 char **tokens, 594 uint32_t n_tokens, 595 uint32_t n_lines, 596 uint32_t *err_line, 597 const char **err_msg) 598 { 599 struct rte_swx_match_field_params *new_fields; 600 enum rte_swx_table_match_type match_type = RTE_SWX_TABLE_MATCH_WILDCARD; 601 char *name; 602 603 /* Handle end of block. */ 604 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 605 *block_mask &= ~(1 << TABLE_KEY_BLOCK); 606 return 0; 607 } 608 609 /* Check input arguments. */ 610 if ((n_tokens != 2) || 611 (strcmp(tokens[1], "exact") && 612 strcmp(tokens[1], "wildcard") && 613 strcmp(tokens[1], "lpm"))) { 614 if (err_line) 615 *err_line = n_lines; 616 if (err_msg) 617 *err_msg = "Invalid match field statement."; 618 return -EINVAL; 619 } 620 621 if (!strcmp(tokens[1], "wildcard")) 622 match_type = RTE_SWX_TABLE_MATCH_WILDCARD; 623 if (!strcmp(tokens[1], "lpm")) 624 match_type = RTE_SWX_TABLE_MATCH_LPM; 625 if (!strcmp(tokens[1], "exact")) 626 match_type = RTE_SWX_TABLE_MATCH_EXACT; 627 628 name = strdup(tokens[0]); 629 if (!name) { 630 if (err_line) 631 *err_line = n_lines; 632 if (err_msg) 633 *err_msg = "Memory allocation failed."; 634 return -ENOMEM; 635 } 636 637 new_fields = realloc(s->params.fields, 638 (s->params.n_fields + 1) * sizeof(struct rte_swx_match_field_params)); 639 if (!new_fields) { 640 free(name); 641 642 if (err_line) 643 *err_line = n_lines; 644 if (err_msg) 645 *err_msg = "Memory allocation failed."; 646 return -ENOMEM; 647 } 648 649 s->params.fields = new_fields; 650 s->params.fields[s->params.n_fields].name = name; 651 s->params.fields[s->params.n_fields].match_type = match_type; 652 s->params.n_fields++; 653 654 return 0; 655 } 656 657 static int 658 table_actions_statement_parse(uint32_t *block_mask, 659 char **tokens, 660 uint32_t n_tokens, 661 uint32_t n_lines, 662 uint32_t *err_line, 663 const char **err_msg) 664 { 665 /* Check format. */ 666 if ((n_tokens != 2) || strcmp(tokens[1], "{")) { 667 if (err_line) 668 *err_line = n_lines; 669 if (err_msg) 670 *err_msg = "Invalid actions statement."; 671 return -EINVAL; 672 } 673 674 /* block_mask. */ 675 *block_mask |= 1 << TABLE_ACTIONS_BLOCK; 676 677 return 0; 678 } 679 680 static int 681 table_actions_block_parse(struct table_spec *s, 682 uint32_t *block_mask, 683 char **tokens, 684 uint32_t n_tokens, 685 uint32_t n_lines, 686 uint32_t *err_line, 687 const char **err_msg) 688 { 689 const char **new_action_names = NULL; 690 int *new_action_is_for_table_entries = NULL, *new_action_is_for_default_entry = NULL; 691 char *name = NULL; 692 int action_is_for_table_entries = 1, action_is_for_default_entry = 1; 693 694 /* Handle end of block. */ 695 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 696 *block_mask &= ~(1 << TABLE_ACTIONS_BLOCK); 697 return 0; 698 } 699 700 /* Check input arguments. */ 701 if ((n_tokens > 2) || 702 ((n_tokens == 2) && strcmp(tokens[1], "@tableonly") && 703 strcmp(tokens[1], "@defaultonly"))) { 704 if (err_line) 705 *err_line = n_lines; 706 if (err_msg) 707 *err_msg = "Invalid action name statement."; 708 return -EINVAL; 709 } 710 711 name = strdup(tokens[0]); 712 713 if (n_tokens == 2) { 714 if (!strcmp(tokens[1], "@tableonly")) 715 action_is_for_default_entry = 0; 716 717 if (!strcmp(tokens[1], "@defaultonly")) 718 action_is_for_table_entries = 0; 719 } 720 721 new_action_names = realloc(s->params.action_names, 722 (s->params.n_actions + 1) * sizeof(char *)); 723 new_action_is_for_table_entries = realloc(s->params.action_is_for_table_entries, 724 (s->params.n_actions + 1) * sizeof(int)); 725 new_action_is_for_default_entry = realloc(s->params.action_is_for_default_entry, 726 (s->params.n_actions + 1) * sizeof(int)); 727 728 if (!name || 729 !new_action_names || 730 !new_action_is_for_table_entries || 731 !new_action_is_for_default_entry) { 732 free(name); 733 free(new_action_names); 734 free(new_action_is_for_table_entries); 735 free(new_action_is_for_default_entry); 736 737 if (err_line) 738 *err_line = n_lines; 739 if (err_msg) 740 *err_msg = "Memory allocation failed."; 741 return -ENOMEM; 742 } 743 744 s->params.action_names = new_action_names; 745 s->params.action_names[s->params.n_actions] = name; 746 747 s->params.action_is_for_table_entries = new_action_is_for_table_entries; 748 s->params.action_is_for_table_entries[s->params.n_actions] = action_is_for_table_entries; 749 750 s->params.action_is_for_default_entry = new_action_is_for_default_entry; 751 s->params.action_is_for_default_entry[s->params.n_actions] = action_is_for_default_entry; 752 753 s->params.n_actions++; 754 755 return 0; 756 } 757 758 static int 759 table_default_action_statement_parse(struct table_spec *s, 760 char **tokens, 761 uint32_t n_tokens, 762 uint32_t n_lines, 763 uint32_t *err_line, 764 const char **err_msg) 765 { 766 uint32_t i; 767 int status = 0, duplicate = 0; 768 769 /* Check format. */ 770 if ((n_tokens < 4) || 771 strcmp(tokens[2], "args")) { 772 status = -EINVAL; 773 goto error; 774 } 775 776 if (s->params.default_action_name) { 777 duplicate = 1; 778 status = -EINVAL; 779 goto error; 780 } 781 782 s->params.default_action_name = strdup(tokens[1]); 783 if (!s->params.default_action_name) { 784 status = -ENOMEM; 785 goto error; 786 } 787 788 if (strcmp(tokens[3], "none")) { 789 char buffer[MAX_LINE_LENGTH]; 790 uint32_t n_tokens_args = n_tokens - 3; 791 792 if (!strcmp(tokens[n_tokens - 1], "const")) 793 n_tokens_args--; 794 795 if (!n_tokens_args) { 796 status = -EINVAL; 797 goto error; 798 } 799 800 buffer[0] = 0; 801 for (i = 0; i < n_tokens_args; i++) { 802 if (i) 803 strcat(buffer, " "); 804 805 strcat(buffer, tokens[3 + i]); 806 } 807 808 s->params.default_action_args = strdup(buffer); 809 if (!s->params.default_action_args) { 810 status = -ENOMEM; 811 goto error; 812 } 813 } else { 814 if (((n_tokens != 4) && (n_tokens != 5)) || 815 ((n_tokens == 5) && (strcmp(tokens[4], "const")))) { 816 status = -EINVAL; 817 goto error; 818 } 819 } 820 821 if (!strcmp(tokens[n_tokens - 1], "const")) 822 s->params.default_action_is_const = 1; 823 824 return 0; 825 826 error: 827 if (err_line) 828 *err_line = n_lines; 829 830 if (err_msg) 831 switch (status) { 832 case -ENOMEM: 833 *err_msg = "Memory allocation failed."; 834 break; 835 836 default: 837 if (duplicate) 838 *err_msg = "Duplicate default_action statement."; 839 840 *err_msg = "Invalid default_action statement."; 841 } 842 843 return status; 844 } 845 846 static int 847 table_statement_parse(struct table_spec *s, 848 uint32_t *block_mask, 849 char **tokens, 850 uint32_t n_tokens, 851 uint32_t n_lines, 852 uint32_t *err_line, 853 const char **err_msg) 854 { 855 /* Check format. */ 856 if ((n_tokens != 3) || strcmp(tokens[2], "{")) { 857 if (err_line) 858 *err_line = n_lines; 859 if (err_msg) 860 *err_msg = "Invalid table statement."; 861 return -EINVAL; 862 } 863 864 /* spec. */ 865 s->name = strdup(tokens[1]); 866 if (!s->name) { 867 if (err_line) 868 *err_line = n_lines; 869 if (err_msg) 870 *err_msg = "Memory allocation failed."; 871 return -ENOMEM; 872 } 873 874 /* block_mask. */ 875 *block_mask |= 1 << TABLE_BLOCK; 876 877 return 0; 878 } 879 880 static int 881 table_block_parse(struct table_spec *s, 882 uint32_t *block_mask, 883 char **tokens, 884 uint32_t n_tokens, 885 uint32_t n_lines, 886 uint32_t *err_line, 887 const char **err_msg) 888 { 889 if (*block_mask & (1 << TABLE_KEY_BLOCK)) 890 return table_key_block_parse(s, 891 block_mask, 892 tokens, 893 n_tokens, 894 n_lines, 895 err_line, 896 err_msg); 897 898 if (*block_mask & (1 << TABLE_ACTIONS_BLOCK)) 899 return table_actions_block_parse(s, 900 block_mask, 901 tokens, 902 n_tokens, 903 n_lines, 904 err_line, 905 err_msg); 906 907 /* Handle end of block. */ 908 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 909 *block_mask &= ~(1 << TABLE_BLOCK); 910 return 0; 911 } 912 913 if (!strcmp(tokens[0], "key")) 914 return table_key_statement_parse(block_mask, 915 tokens, 916 n_tokens, 917 n_lines, 918 err_line, 919 err_msg); 920 921 if (!strcmp(tokens[0], "actions")) 922 return table_actions_statement_parse(block_mask, 923 tokens, 924 n_tokens, 925 n_lines, 926 err_line, 927 err_msg); 928 929 if (!strcmp(tokens[0], "default_action")) 930 return table_default_action_statement_parse(s, 931 tokens, 932 n_tokens, 933 n_lines, 934 err_line, 935 err_msg); 936 937 if (!strcmp(tokens[0], "hash")) { 938 if (n_tokens != 2) { 939 if (err_line) 940 *err_line = n_lines; 941 if (err_msg) 942 *err_msg = "Invalid hash statement."; 943 return -EINVAL; 944 } 945 946 if (s->params.hash_func_name) { 947 if (err_line) 948 *err_line = n_lines; 949 if (err_msg) 950 *err_msg = "Duplicate hash statement."; 951 return -EINVAL; 952 } 953 954 s->params.hash_func_name = strdup(tokens[1]); 955 if (!s->params.hash_func_name) { 956 if (err_line) 957 *err_line = n_lines; 958 if (err_msg) 959 *err_msg = "Memory allocation failed."; 960 return -ENOMEM; 961 } 962 963 return 0; 964 } 965 966 if (!strcmp(tokens[0], "instanceof")) { 967 if (n_tokens != 2) { 968 if (err_line) 969 *err_line = n_lines; 970 if (err_msg) 971 *err_msg = "Invalid instanceof statement."; 972 return -EINVAL; 973 } 974 975 if (s->recommended_table_type_name) { 976 if (err_line) 977 *err_line = n_lines; 978 if (err_msg) 979 *err_msg = "Duplicate instanceof statement."; 980 return -EINVAL; 981 } 982 983 s->recommended_table_type_name = strdup(tokens[1]); 984 if (!s->recommended_table_type_name) { 985 if (err_line) 986 *err_line = n_lines; 987 if (err_msg) 988 *err_msg = "Memory allocation failed."; 989 return -ENOMEM; 990 } 991 992 return 0; 993 } 994 995 if (!strcmp(tokens[0], "pragma")) { 996 if (n_tokens != 2) { 997 if (err_line) 998 *err_line = n_lines; 999 if (err_msg) 1000 *err_msg = "Invalid pragma statement."; 1001 return -EINVAL; 1002 } 1003 1004 if (s->args) { 1005 if (err_line) 1006 *err_line = n_lines; 1007 if (err_msg) 1008 *err_msg = "Duplicate pragma statement."; 1009 return -EINVAL; 1010 } 1011 1012 s->args = strdup(tokens[1]); 1013 if (!s->args) { 1014 if (err_line) 1015 *err_line = n_lines; 1016 if (err_msg) 1017 *err_msg = "Memory allocation failed."; 1018 return -ENOMEM; 1019 } 1020 1021 return 0; 1022 } 1023 1024 if (!strcmp(tokens[0], "size")) { 1025 char *p = tokens[1]; 1026 1027 if (n_tokens != 2) { 1028 if (err_line) 1029 *err_line = n_lines; 1030 if (err_msg) 1031 *err_msg = "Invalid pragma statement."; 1032 return -EINVAL; 1033 } 1034 1035 s->size = strtoul(p, &p, 0); 1036 if (p[0]) { 1037 if (err_line) 1038 *err_line = n_lines; 1039 if (err_msg) 1040 *err_msg = "Invalid size argument."; 1041 return -EINVAL; 1042 } 1043 1044 return 0; 1045 } 1046 1047 /* Anything else. */ 1048 if (err_line) 1049 *err_line = n_lines; 1050 if (err_msg) 1051 *err_msg = "Invalid statement."; 1052 return -EINVAL; 1053 } 1054 1055 /* 1056 * selector. 1057 */ 1058 static void 1059 selector_spec_free(struct selector_spec *s) 1060 { 1061 uintptr_t field_name; 1062 uint32_t i; 1063 1064 if (!s) 1065 return; 1066 1067 /* name. */ 1068 free(s->name); 1069 s->name = NULL; 1070 1071 /* params->group_id_field_name. */ 1072 field_name = (uintptr_t)s->params.group_id_field_name; 1073 free((void *)field_name); 1074 s->params.group_id_field_name = NULL; 1075 1076 /* params->selector_field_names. */ 1077 for (i = 0; i < s->params.n_selector_fields; i++) { 1078 field_name = (uintptr_t)s->params.selector_field_names[i]; 1079 1080 free((void *)field_name); 1081 } 1082 1083 free(s->params.selector_field_names); 1084 s->params.selector_field_names = NULL; 1085 1086 s->params.n_selector_fields = 0; 1087 1088 /* params->member_id_field_name. */ 1089 field_name = (uintptr_t)s->params.member_id_field_name; 1090 free((void *)field_name); 1091 s->params.member_id_field_name = NULL; 1092 1093 /* params->n_groups_max. */ 1094 s->params.n_groups_max = 0; 1095 1096 /* params->n_members_per_group_max. */ 1097 s->params.n_members_per_group_max = 0; 1098 } 1099 1100 static int 1101 selector_statement_parse(struct selector_spec *s, 1102 uint32_t *block_mask, 1103 char **tokens, 1104 uint32_t n_tokens, 1105 uint32_t n_lines, 1106 uint32_t *err_line, 1107 const char **err_msg) 1108 { 1109 /* Check format. */ 1110 if ((n_tokens != 3) || strcmp(tokens[2], "{")) { 1111 if (err_line) 1112 *err_line = n_lines; 1113 if (err_msg) 1114 *err_msg = "Invalid selector statement."; 1115 return -EINVAL; 1116 } 1117 1118 /* spec. */ 1119 s->name = strdup(tokens[1]); 1120 if (!s->name) { 1121 if (err_line) 1122 *err_line = n_lines; 1123 if (err_msg) 1124 *err_msg = "Memory allocation failed."; 1125 return -ENOMEM; 1126 } 1127 1128 /* block_mask. */ 1129 *block_mask |= 1 << SELECTOR_BLOCK; 1130 1131 return 0; 1132 } 1133 1134 static int 1135 selector_selector_statement_parse(uint32_t *block_mask, 1136 char **tokens, 1137 uint32_t n_tokens, 1138 uint32_t n_lines, 1139 uint32_t *err_line, 1140 const char **err_msg) 1141 { 1142 /* Check format. */ 1143 if ((n_tokens != 2) || strcmp(tokens[1], "{")) { 1144 if (err_line) 1145 *err_line = n_lines; 1146 if (err_msg) 1147 *err_msg = "Invalid selector statement."; 1148 return -EINVAL; 1149 } 1150 1151 /* block_mask. */ 1152 *block_mask |= 1 << SELECTOR_SELECTOR_BLOCK; 1153 1154 return 0; 1155 } 1156 1157 static int 1158 selector_selector_block_parse(struct selector_spec *s, 1159 uint32_t *block_mask, 1160 char **tokens, 1161 uint32_t n_tokens, 1162 uint32_t n_lines, 1163 uint32_t *err_line, 1164 const char **err_msg) 1165 { 1166 const char **new_fields; 1167 char *name; 1168 1169 /* Handle end of block. */ 1170 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 1171 *block_mask &= ~(1 << SELECTOR_SELECTOR_BLOCK); 1172 return 0; 1173 } 1174 1175 /* Check input arguments. */ 1176 if (n_tokens != 1) { 1177 if (err_line) 1178 *err_line = n_lines; 1179 if (err_msg) 1180 *err_msg = "Invalid selector field statement."; 1181 return -EINVAL; 1182 } 1183 1184 name = strdup(tokens[0]); 1185 if (!name) { 1186 if (err_line) 1187 *err_line = n_lines; 1188 if (err_msg) 1189 *err_msg = "Memory allocation failed."; 1190 return -ENOMEM; 1191 } 1192 1193 new_fields = realloc(s->params.selector_field_names, 1194 (s->params.n_selector_fields + 1) * sizeof(char *)); 1195 if (!new_fields) { 1196 free(name); 1197 1198 if (err_line) 1199 *err_line = n_lines; 1200 if (err_msg) 1201 *err_msg = "Memory allocation failed."; 1202 return -ENOMEM; 1203 } 1204 1205 s->params.selector_field_names = new_fields; 1206 s->params.selector_field_names[s->params.n_selector_fields] = name; 1207 s->params.n_selector_fields++; 1208 1209 return 0; 1210 } 1211 1212 static int 1213 selector_block_parse(struct selector_spec *s, 1214 uint32_t *block_mask, 1215 char **tokens, 1216 uint32_t n_tokens, 1217 uint32_t n_lines, 1218 uint32_t *err_line, 1219 const char **err_msg) 1220 { 1221 if (*block_mask & (1 << SELECTOR_SELECTOR_BLOCK)) 1222 return selector_selector_block_parse(s, 1223 block_mask, 1224 tokens, 1225 n_tokens, 1226 n_lines, 1227 err_line, 1228 err_msg); 1229 1230 /* Handle end of block. */ 1231 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 1232 *block_mask &= ~(1 << SELECTOR_BLOCK); 1233 return 0; 1234 } 1235 1236 if (!strcmp(tokens[0], "group_id")) { 1237 if (n_tokens != 2) { 1238 if (err_line) 1239 *err_line = n_lines; 1240 if (err_msg) 1241 *err_msg = "Invalid group_id statement."; 1242 return -EINVAL; 1243 } 1244 1245 s->params.group_id_field_name = strdup(tokens[1]); 1246 if (!s->params.group_id_field_name) { 1247 if (err_line) 1248 *err_line = n_lines; 1249 if (err_msg) 1250 *err_msg = "Memory allocation failed."; 1251 return -ENOMEM; 1252 } 1253 1254 return 0; 1255 } 1256 1257 if (!strcmp(tokens[0], "selector")) 1258 return selector_selector_statement_parse(block_mask, 1259 tokens, 1260 n_tokens, 1261 n_lines, 1262 err_line, 1263 err_msg); 1264 1265 if (!strcmp(tokens[0], "member_id")) { 1266 if (n_tokens != 2) { 1267 if (err_line) 1268 *err_line = n_lines; 1269 if (err_msg) 1270 *err_msg = "Invalid member_id statement."; 1271 return -EINVAL; 1272 } 1273 1274 s->params.member_id_field_name = strdup(tokens[1]); 1275 if (!s->params.member_id_field_name) { 1276 if (err_line) 1277 *err_line = n_lines; 1278 if (err_msg) 1279 *err_msg = "Memory allocation failed."; 1280 return -ENOMEM; 1281 } 1282 1283 return 0; 1284 } 1285 1286 if (!strcmp(tokens[0], "n_groups_max")) { 1287 char *p = tokens[1]; 1288 1289 if (n_tokens != 2) { 1290 if (err_line) 1291 *err_line = n_lines; 1292 if (err_msg) 1293 *err_msg = "Invalid n_groups statement."; 1294 return -EINVAL; 1295 } 1296 1297 s->params.n_groups_max = strtoul(p, &p, 0); 1298 if (p[0]) { 1299 if (err_line) 1300 *err_line = n_lines; 1301 if (err_msg) 1302 *err_msg = "Invalid n_groups argument."; 1303 return -EINVAL; 1304 } 1305 1306 return 0; 1307 } 1308 1309 if (!strcmp(tokens[0], "n_members_per_group_max")) { 1310 char *p = tokens[1]; 1311 1312 if (n_tokens != 2) { 1313 if (err_line) 1314 *err_line = n_lines; 1315 if (err_msg) 1316 *err_msg = "Invalid n_members_per_group statement."; 1317 return -EINVAL; 1318 } 1319 1320 s->params.n_members_per_group_max = strtoul(p, &p, 0); 1321 if (p[0]) { 1322 if (err_line) 1323 *err_line = n_lines; 1324 if (err_msg) 1325 *err_msg = "Invalid n_members_per_group argument."; 1326 return -EINVAL; 1327 } 1328 1329 return 0; 1330 } 1331 1332 /* Anything else. */ 1333 if (err_line) 1334 *err_line = n_lines; 1335 if (err_msg) 1336 *err_msg = "Invalid statement."; 1337 return -EINVAL; 1338 } 1339 1340 /* 1341 * learner. 1342 */ 1343 static void 1344 learner_spec_free(struct learner_spec *s) 1345 { 1346 uintptr_t default_action_name, default_action_args, hash_func_name; 1347 uint32_t i; 1348 1349 if (!s) 1350 return; 1351 1352 free(s->name); 1353 s->name = NULL; 1354 1355 for (i = 0; i < s->params.n_fields; i++) { 1356 uintptr_t name = (uintptr_t)s->params.field_names[i]; 1357 1358 free((void *)name); 1359 } 1360 1361 free(s->params.field_names); 1362 s->params.field_names = NULL; 1363 1364 s->params.n_fields = 0; 1365 1366 for (i = 0; i < s->params.n_actions; i++) { 1367 uintptr_t name = (uintptr_t)s->params.action_names[i]; 1368 1369 free((void *)name); 1370 } 1371 1372 free(s->params.action_names); 1373 s->params.action_names = NULL; 1374 1375 s->params.n_actions = 0; 1376 1377 default_action_name = (uintptr_t)s->params.default_action_name; 1378 free((void *)default_action_name); 1379 s->params.default_action_name = NULL; 1380 1381 default_action_args = (uintptr_t)s->params.default_action_args; 1382 free((void *)default_action_args); 1383 s->params.default_action_args = NULL; 1384 1385 free(s->params.action_is_for_table_entries); 1386 s->params.action_is_for_table_entries = NULL; 1387 1388 free(s->params.action_is_for_default_entry); 1389 s->params.action_is_for_default_entry = NULL; 1390 1391 s->params.default_action_is_const = 0; 1392 1393 hash_func_name = (uintptr_t)s->params.hash_func_name; 1394 free((void *)hash_func_name); 1395 s->params.hash_func_name = NULL; 1396 1397 s->size = 0; 1398 1399 free(s->timeout); 1400 s->timeout = NULL; 1401 1402 s->n_timeouts = 0; 1403 } 1404 1405 static int 1406 learner_key_statement_parse(uint32_t *block_mask, 1407 char **tokens, 1408 uint32_t n_tokens, 1409 uint32_t n_lines, 1410 uint32_t *err_line, 1411 const char **err_msg) 1412 { 1413 /* Check format. */ 1414 if ((n_tokens != 2) || strcmp(tokens[1], "{")) { 1415 if (err_line) 1416 *err_line = n_lines; 1417 if (err_msg) 1418 *err_msg = "Invalid key statement."; 1419 return -EINVAL; 1420 } 1421 1422 /* block_mask. */ 1423 *block_mask |= 1 << LEARNER_KEY_BLOCK; 1424 1425 return 0; 1426 } 1427 1428 static int 1429 learner_key_block_parse(struct learner_spec *s, 1430 uint32_t *block_mask, 1431 char **tokens, 1432 uint32_t n_tokens, 1433 uint32_t n_lines, 1434 uint32_t *err_line, 1435 const char **err_msg) 1436 { 1437 const char **new_field_names = NULL; 1438 char *field_name = NULL; 1439 1440 /* Handle end of block. */ 1441 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 1442 *block_mask &= ~(1 << LEARNER_KEY_BLOCK); 1443 return 0; 1444 } 1445 1446 /* Check input arguments. */ 1447 if (n_tokens != 1) { 1448 if (err_line) 1449 *err_line = n_lines; 1450 if (err_msg) 1451 *err_msg = "Invalid match field statement."; 1452 return -EINVAL; 1453 } 1454 1455 field_name = strdup(tokens[0]); 1456 new_field_names = realloc(s->params.field_names, (s->params.n_fields + 1) * sizeof(char *)); 1457 if (!field_name || !new_field_names) { 1458 free(field_name); 1459 free(new_field_names); 1460 1461 if (err_line) 1462 *err_line = n_lines; 1463 if (err_msg) 1464 *err_msg = "Memory allocation failed."; 1465 return -ENOMEM; 1466 } 1467 1468 s->params.field_names = new_field_names; 1469 s->params.field_names[s->params.n_fields] = field_name; 1470 s->params.n_fields++; 1471 1472 return 0; 1473 } 1474 1475 static int 1476 learner_actions_statement_parse(uint32_t *block_mask, 1477 char **tokens, 1478 uint32_t n_tokens, 1479 uint32_t n_lines, 1480 uint32_t *err_line, 1481 const char **err_msg) 1482 { 1483 /* Check format. */ 1484 if ((n_tokens != 2) || strcmp(tokens[1], "{")) { 1485 if (err_line) 1486 *err_line = n_lines; 1487 if (err_msg) 1488 *err_msg = "Invalid actions statement."; 1489 return -EINVAL; 1490 } 1491 1492 /* block_mask. */ 1493 *block_mask |= 1 << LEARNER_ACTIONS_BLOCK; 1494 1495 return 0; 1496 } 1497 1498 static int 1499 learner_actions_block_parse(struct learner_spec *s, 1500 uint32_t *block_mask, 1501 char **tokens, 1502 uint32_t n_tokens, 1503 uint32_t n_lines, 1504 uint32_t *err_line, 1505 const char **err_msg) 1506 { 1507 const char **new_action_names = NULL; 1508 int *new_action_is_for_table_entries = NULL, *new_action_is_for_default_entry = NULL; 1509 char *name = NULL; 1510 int action_is_for_table_entries = 1, action_is_for_default_entry = 1; 1511 1512 /* Handle end of block. */ 1513 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 1514 *block_mask &= ~(1 << LEARNER_ACTIONS_BLOCK); 1515 return 0; 1516 } 1517 1518 /* Check input arguments. */ 1519 if ((n_tokens > 2) || 1520 ((n_tokens == 2) && strcmp(tokens[1], "@tableonly") && 1521 strcmp(tokens[1], "@defaultonly"))) { 1522 if (err_line) 1523 *err_line = n_lines; 1524 if (err_msg) 1525 *err_msg = "Invalid action name statement."; 1526 return -EINVAL; 1527 } 1528 1529 name = strdup(tokens[0]); 1530 1531 if (n_tokens == 2) { 1532 if (!strcmp(tokens[1], "@tableonly")) 1533 action_is_for_default_entry = 0; 1534 1535 if (!strcmp(tokens[1], "@defaultonly")) 1536 action_is_for_table_entries = 0; 1537 } 1538 1539 new_action_names = realloc(s->params.action_names, 1540 (s->params.n_actions + 1) * sizeof(char *)); 1541 new_action_is_for_table_entries = realloc(s->params.action_is_for_table_entries, 1542 (s->params.n_actions + 1) * sizeof(int)); 1543 new_action_is_for_default_entry = realloc(s->params.action_is_for_default_entry, 1544 (s->params.n_actions + 1) * sizeof(int)); 1545 1546 if (!name || 1547 !new_action_names || 1548 !new_action_is_for_table_entries || 1549 !new_action_is_for_default_entry) { 1550 free(name); 1551 free(new_action_names); 1552 free(new_action_is_for_table_entries); 1553 free(new_action_is_for_default_entry); 1554 1555 if (err_line) 1556 *err_line = n_lines; 1557 if (err_msg) 1558 *err_msg = "Memory allocation failed."; 1559 return -ENOMEM; 1560 } 1561 1562 s->params.action_names = new_action_names; 1563 s->params.action_names[s->params.n_actions] = name; 1564 1565 s->params.action_is_for_table_entries = new_action_is_for_table_entries; 1566 s->params.action_is_for_table_entries[s->params.n_actions] = action_is_for_table_entries; 1567 1568 s->params.action_is_for_default_entry = new_action_is_for_default_entry; 1569 s->params.action_is_for_default_entry[s->params.n_actions] = action_is_for_default_entry; 1570 1571 s->params.n_actions++; 1572 1573 return 0; 1574 } 1575 1576 static int 1577 learner_default_action_statement_parse(struct learner_spec *s, 1578 char **tokens, 1579 uint32_t n_tokens, 1580 uint32_t n_lines, 1581 uint32_t *err_line, 1582 const char **err_msg) 1583 { 1584 uint32_t i; 1585 int status = 0, duplicate = 0; 1586 1587 /* Check format. */ 1588 if ((n_tokens < 4) || 1589 strcmp(tokens[2], "args")) { 1590 status = -EINVAL; 1591 goto error; 1592 } 1593 1594 if (s->params.default_action_name) { 1595 duplicate = 1; 1596 status = -EINVAL; 1597 goto error; 1598 } 1599 1600 s->params.default_action_name = strdup(tokens[1]); 1601 if (!s->params.default_action_name) { 1602 status = -ENOMEM; 1603 goto error; 1604 } 1605 1606 if (strcmp(tokens[3], "none")) { 1607 char buffer[MAX_LINE_LENGTH]; 1608 uint32_t n_tokens_args = n_tokens - 3; 1609 1610 if (!strcmp(tokens[n_tokens - 1], "const")) 1611 n_tokens_args--; 1612 1613 if (!n_tokens_args) { 1614 status = -EINVAL; 1615 goto error; 1616 } 1617 1618 buffer[0] = 0; 1619 for (i = 0; i < n_tokens_args; i++) { 1620 if (i) 1621 strcat(buffer, " "); 1622 1623 strcat(buffer, tokens[3 + i]); 1624 } 1625 1626 s->params.default_action_args = strdup(buffer); 1627 if (!s->params.default_action_args) { 1628 status = -ENOMEM; 1629 goto error; 1630 } 1631 } else { 1632 if (((n_tokens != 4) && (n_tokens != 5)) || 1633 ((n_tokens == 5) && (strcmp(tokens[4], "const")))) { 1634 status = -EINVAL; 1635 goto error; 1636 } 1637 } 1638 1639 if (!strcmp(tokens[n_tokens - 1], "const")) 1640 s->params.default_action_is_const = 1; 1641 1642 return 0; 1643 1644 error: 1645 if (err_line) 1646 *err_line = n_lines; 1647 1648 if (err_msg) 1649 switch (status) { 1650 case -ENOMEM: 1651 *err_msg = "Memory allocation failed."; 1652 break; 1653 1654 default: 1655 if (duplicate) 1656 *err_msg = "Duplicate default_action statement."; 1657 1658 *err_msg = "Invalid default_action statement."; 1659 } 1660 1661 return status; 1662 } 1663 1664 static int 1665 learner_timeout_statement_parse(uint32_t *block_mask, 1666 char **tokens, 1667 uint32_t n_tokens, 1668 uint32_t n_lines, 1669 uint32_t *err_line, 1670 const char **err_msg) 1671 { 1672 /* Check format. */ 1673 if ((n_tokens != 2) || strcmp(tokens[1], "{")) { 1674 if (err_line) 1675 *err_line = n_lines; 1676 if (err_msg) 1677 *err_msg = "Invalid timeout statement."; 1678 return -EINVAL; 1679 } 1680 1681 /* block_mask. */ 1682 *block_mask |= 1 << LEARNER_TIMEOUT_BLOCK; 1683 1684 return 0; 1685 } 1686 1687 static int 1688 learner_timeout_block_parse(struct learner_spec *s, 1689 uint32_t *block_mask, 1690 char **tokens, 1691 uint32_t n_tokens, 1692 uint32_t n_lines, 1693 uint32_t *err_line, 1694 const char **err_msg) 1695 { 1696 uint32_t *new_timeout = NULL; 1697 char *str; 1698 uint32_t val; 1699 int status = 0; 1700 1701 /* Handle end of block. */ 1702 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 1703 *block_mask &= ~(1 << LEARNER_TIMEOUT_BLOCK); 1704 return 0; 1705 } 1706 1707 /* Check input arguments. */ 1708 if (n_tokens != 1) { 1709 status = -EINVAL; 1710 goto error; 1711 } 1712 1713 str = tokens[0]; 1714 val = strtoul(str, &str, 0); 1715 if (str[0]) { 1716 status = -EINVAL; 1717 goto error; 1718 } 1719 1720 new_timeout = realloc(s->timeout, (s->n_timeouts + 1) * sizeof(uint32_t)); 1721 if (!new_timeout) { 1722 status = -ENOMEM; 1723 goto error; 1724 } 1725 1726 s->timeout = new_timeout; 1727 s->timeout[s->n_timeouts] = val; 1728 s->n_timeouts++; 1729 1730 return 0; 1731 1732 error: 1733 free(new_timeout); 1734 1735 if (err_line) 1736 *err_line = n_lines; 1737 1738 if (err_msg) 1739 switch (status) { 1740 case -ENOMEM: 1741 *err_msg = "Memory allocation failed."; 1742 break; 1743 1744 default: 1745 *err_msg = "Invalid timeout value statement."; 1746 break; 1747 } 1748 1749 return status; 1750 } 1751 1752 1753 static int 1754 learner_statement_parse(struct learner_spec *s, 1755 uint32_t *block_mask, 1756 char **tokens, 1757 uint32_t n_tokens, 1758 uint32_t n_lines, 1759 uint32_t *err_line, 1760 const char **err_msg) 1761 { 1762 /* Check format. */ 1763 if ((n_tokens != 3) || strcmp(tokens[2], "{")) { 1764 if (err_line) 1765 *err_line = n_lines; 1766 if (err_msg) 1767 *err_msg = "Invalid learner statement."; 1768 return -EINVAL; 1769 } 1770 1771 /* spec. */ 1772 s->name = strdup(tokens[1]); 1773 if (!s->name) { 1774 if (err_line) 1775 *err_line = n_lines; 1776 if (err_msg) 1777 *err_msg = "Memory allocation failed."; 1778 return -ENOMEM; 1779 } 1780 1781 /* block_mask. */ 1782 *block_mask |= 1 << LEARNER_BLOCK; 1783 1784 return 0; 1785 } 1786 1787 static int 1788 learner_block_parse(struct learner_spec *s, 1789 uint32_t *block_mask, 1790 char **tokens, 1791 uint32_t n_tokens, 1792 uint32_t n_lines, 1793 uint32_t *err_line, 1794 const char **err_msg) 1795 { 1796 if (*block_mask & (1 << LEARNER_KEY_BLOCK)) 1797 return learner_key_block_parse(s, 1798 block_mask, 1799 tokens, 1800 n_tokens, 1801 n_lines, 1802 err_line, 1803 err_msg); 1804 1805 if (*block_mask & (1 << LEARNER_ACTIONS_BLOCK)) 1806 return learner_actions_block_parse(s, 1807 block_mask, 1808 tokens, 1809 n_tokens, 1810 n_lines, 1811 err_line, 1812 err_msg); 1813 1814 if (*block_mask & (1 << LEARNER_TIMEOUT_BLOCK)) 1815 return learner_timeout_block_parse(s, 1816 block_mask, 1817 tokens, 1818 n_tokens, 1819 n_lines, 1820 err_line, 1821 err_msg); 1822 1823 /* Handle end of block. */ 1824 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 1825 *block_mask &= ~(1 << LEARNER_BLOCK); 1826 return 0; 1827 } 1828 1829 if (!strcmp(tokens[0], "key")) 1830 return learner_key_statement_parse(block_mask, 1831 tokens, 1832 n_tokens, 1833 n_lines, 1834 err_line, 1835 err_msg); 1836 1837 if (!strcmp(tokens[0], "actions")) 1838 return learner_actions_statement_parse(block_mask, 1839 tokens, 1840 n_tokens, 1841 n_lines, 1842 err_line, 1843 err_msg); 1844 1845 if (!strcmp(tokens[0], "default_action")) 1846 return learner_default_action_statement_parse(s, 1847 tokens, 1848 n_tokens, 1849 n_lines, 1850 err_line, 1851 err_msg); 1852 1853 if (!strcmp(tokens[0], "hash")) { 1854 if (n_tokens != 2) { 1855 if (err_line) 1856 *err_line = n_lines; 1857 if (err_msg) 1858 *err_msg = "Invalid hash statement."; 1859 return -EINVAL; 1860 } 1861 1862 if (s->params.hash_func_name) { 1863 if (err_line) 1864 *err_line = n_lines; 1865 if (err_msg) 1866 *err_msg = "Duplicate hash statement."; 1867 return -EINVAL; 1868 } 1869 1870 s->params.hash_func_name = strdup(tokens[1]); 1871 if (!s->params.hash_func_name) { 1872 if (err_line) 1873 *err_line = n_lines; 1874 if (err_msg) 1875 *err_msg = "Memory allocation failed."; 1876 return -ENOMEM; 1877 } 1878 1879 return 0; 1880 } 1881 1882 if (!strcmp(tokens[0], "size")) { 1883 char *p = tokens[1]; 1884 1885 if (n_tokens != 2) { 1886 if (err_line) 1887 *err_line = n_lines; 1888 if (err_msg) 1889 *err_msg = "Invalid size statement."; 1890 return -EINVAL; 1891 } 1892 1893 s->size = strtoul(p, &p, 0); 1894 if (p[0]) { 1895 if (err_line) 1896 *err_line = n_lines; 1897 if (err_msg) 1898 *err_msg = "Invalid size argument."; 1899 return -EINVAL; 1900 } 1901 1902 return 0; 1903 } 1904 1905 if (!strcmp(tokens[0], "timeout")) 1906 return learner_timeout_statement_parse(block_mask, 1907 tokens, 1908 n_tokens, 1909 n_lines, 1910 err_line, 1911 err_msg); 1912 1913 /* Anything else. */ 1914 if (err_line) 1915 *err_line = n_lines; 1916 if (err_msg) 1917 *err_msg = "Invalid statement."; 1918 return -EINVAL; 1919 } 1920 1921 /* 1922 * regarray. 1923 */ 1924 static void 1925 regarray_spec_free(struct regarray_spec *s) 1926 { 1927 if (!s) 1928 return; 1929 1930 free(s->name); 1931 s->name = NULL; 1932 } 1933 1934 static int 1935 regarray_statement_parse(struct regarray_spec *s, 1936 char **tokens, 1937 uint32_t n_tokens, 1938 uint32_t n_lines, 1939 uint32_t *err_line, 1940 const char **err_msg) 1941 { 1942 char *p; 1943 1944 /* Check format. */ 1945 if ((n_tokens != 6) || 1946 strcmp(tokens[2], "size") || 1947 strcmp(tokens[4], "initval")) { 1948 if (err_line) 1949 *err_line = n_lines; 1950 if (err_msg) 1951 *err_msg = "Invalid regarray statement."; 1952 return -EINVAL; 1953 } 1954 1955 /* spec. */ 1956 s->name = strdup(tokens[1]); 1957 if (!s->name) { 1958 if (err_line) 1959 *err_line = n_lines; 1960 if (err_msg) 1961 *err_msg = "Memory allocation failed."; 1962 return -ENOMEM; 1963 } 1964 1965 p = tokens[3]; 1966 s->size = strtoul(p, &p, 0); 1967 if (p[0] || !s->size) { 1968 if (err_line) 1969 *err_line = n_lines; 1970 if (err_msg) 1971 *err_msg = "Invalid size argument."; 1972 return -EINVAL; 1973 } 1974 1975 p = tokens[5]; 1976 s->init_val = strtoull(p, &p, 0); 1977 if (p[0]) { 1978 if (err_line) 1979 *err_line = n_lines; 1980 if (err_msg) 1981 *err_msg = "Invalid initval argument."; 1982 return -EINVAL; 1983 } 1984 1985 return 0; 1986 } 1987 1988 /* 1989 * metarray. 1990 */ 1991 static void 1992 metarray_spec_free(struct metarray_spec *s) 1993 { 1994 if (!s) 1995 return; 1996 1997 free(s->name); 1998 s->name = NULL; 1999 } 2000 2001 static int 2002 metarray_statement_parse(struct metarray_spec *s, 2003 char **tokens, 2004 uint32_t n_tokens, 2005 uint32_t n_lines, 2006 uint32_t *err_line, 2007 const char **err_msg) 2008 { 2009 char *p; 2010 2011 /* Check format. */ 2012 if ((n_tokens != 4) || strcmp(tokens[2], "size")) { 2013 if (err_line) 2014 *err_line = n_lines; 2015 if (err_msg) 2016 *err_msg = "Invalid metarray statement."; 2017 return -EINVAL; 2018 } 2019 2020 /* spec. */ 2021 s->name = strdup(tokens[1]); 2022 if (!s->name) { 2023 if (err_line) 2024 *err_line = n_lines; 2025 if (err_msg) 2026 *err_msg = "Memory allocation failed."; 2027 return -ENOMEM; 2028 } 2029 2030 p = tokens[3]; 2031 s->size = strtoul(p, &p, 0); 2032 if (p[0] || !s->size) { 2033 if (err_line) 2034 *err_line = n_lines; 2035 if (err_msg) 2036 *err_msg = "Invalid size argument."; 2037 return -EINVAL; 2038 } 2039 2040 return 0; 2041 } 2042 2043 /* 2044 * 2045 * rss 2046 */ 2047 2048 static void 2049 rss_spec_free(struct rss_spec *s) 2050 { 2051 if (!s) 2052 return; 2053 2054 free(s->name); 2055 s->name = NULL; 2056 } 2057 2058 static int 2059 rss_statement_parse(struct rss_spec *s, 2060 char **tokens, 2061 uint32_t n_tokens, 2062 uint32_t n_lines, 2063 uint32_t *err_line, 2064 const char **err_msg) 2065 { 2066 /* Check format. */ 2067 if ((n_tokens != 2)) { 2068 if (err_line) 2069 *err_line = n_lines; 2070 if (err_msg) 2071 *err_msg = "Invalid rss statement."; 2072 return -EINVAL; 2073 } 2074 2075 /* spec. */ 2076 s->name = strdup(tokens[1]); 2077 if (!s->name) { 2078 if (err_line) 2079 *err_line = n_lines; 2080 if (err_msg) 2081 *err_msg = "Memory allocation failed."; 2082 return -ENOMEM; 2083 } 2084 2085 return 0; 2086 } 2087 2088 /* 2089 * apply. 2090 */ 2091 static void 2092 apply_spec_free(struct apply_spec *s) 2093 { 2094 uint32_t i; 2095 2096 if (!s) 2097 return; 2098 2099 for (i = 0; i < s->n_instructions; i++) { 2100 uintptr_t instr = (uintptr_t)s->instructions[i]; 2101 2102 free((void *)instr); 2103 } 2104 2105 free(s->instructions); 2106 s->instructions = NULL; 2107 2108 s->n_instructions = 0; 2109 } 2110 2111 static int 2112 apply_statement_parse(uint32_t *block_mask, 2113 char **tokens, 2114 uint32_t n_tokens, 2115 uint32_t n_lines, 2116 uint32_t *err_line, 2117 const char **err_msg) 2118 { 2119 /* Check format. */ 2120 if ((n_tokens != 2) || strcmp(tokens[1], "{")) { 2121 if (err_line) 2122 *err_line = n_lines; 2123 if (err_msg) 2124 *err_msg = "Invalid apply statement."; 2125 return -EINVAL; 2126 } 2127 2128 /* block_mask. */ 2129 *block_mask |= 1 << APPLY_BLOCK; 2130 2131 return 0; 2132 } 2133 2134 static int 2135 apply_block_parse(struct apply_spec *s, 2136 uint32_t *block_mask, 2137 char **tokens, 2138 uint32_t n_tokens, 2139 uint32_t n_lines, 2140 uint32_t *err_line, 2141 const char **err_msg) 2142 { 2143 char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr; 2144 const char **new_instructions; 2145 uint32_t i; 2146 2147 /* Handle end of block. */ 2148 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 2149 *block_mask &= ~(1 << APPLY_BLOCK); 2150 return 0; 2151 } 2152 2153 /* spec. */ 2154 buffer[0] = 0; 2155 for (i = 0; i < n_tokens; i++) { 2156 if (i) 2157 strcat(buffer, " "); 2158 strcat(buffer, tokens[i]); 2159 } 2160 2161 instr = strdup(buffer); 2162 if (!instr) { 2163 if (err_line) 2164 *err_line = n_lines; 2165 if (err_msg) 2166 *err_msg = "Memory allocation failed."; 2167 return -ENOMEM; 2168 } 2169 2170 new_instructions = realloc(s->instructions, 2171 (s->n_instructions + 1) * sizeof(char *)); 2172 if (!new_instructions) { 2173 free(instr); 2174 2175 if (err_line) 2176 *err_line = n_lines; 2177 if (err_msg) 2178 *err_msg = "Memory allocation failed."; 2179 return -ENOMEM; 2180 } 2181 2182 s->instructions = new_instructions; 2183 s->instructions[s->n_instructions] = instr; 2184 s->n_instructions++; 2185 2186 return 0; 2187 } 2188 2189 /* 2190 * Pipeline. 2191 */ 2192 void 2193 pipeline_spec_free(struct pipeline_spec *s) 2194 { 2195 if (!s) 2196 return; 2197 2198 free(s->extobjs); 2199 free(s->structs); 2200 free(s->headers); 2201 free(s->metadata); 2202 free(s->actions); 2203 free(s->tables); 2204 free(s->selectors); 2205 free(s->learners); 2206 free(s->regarrays); 2207 free(s->metarrays); 2208 free(s->apply); 2209 2210 memset(s, 0, sizeof(struct pipeline_spec)); 2211 } 2212 2213 static const char * 2214 match_type_string_get(enum rte_swx_table_match_type match_type) 2215 { 2216 switch (match_type) { 2217 case RTE_SWX_TABLE_MATCH_WILDCARD: return "RTE_SWX_TABLE_MATCH_WILDCARD"; 2218 case RTE_SWX_TABLE_MATCH_LPM: return "RTE_SWX_TABLE_MATCH_LPM"; 2219 case RTE_SWX_TABLE_MATCH_EXACT: return "RTE_SWX_TABLE_MATCH_EXACT"; 2220 default: return "RTE_SWX_TABLE_MATCH_UNKNOWN"; 2221 } 2222 } 2223 2224 void 2225 pipeline_spec_codegen(FILE *f, 2226 struct pipeline_spec *s) 2227 { 2228 uint32_t i; 2229 2230 /* Check the input arguments. */ 2231 if (!f || !s) 2232 return; 2233 2234 /* extobj. */ 2235 fprintf(f, "static struct extobj_spec extobjs[] = {\n"); 2236 2237 for (i = 0; i < s->n_extobjs; i++) { 2238 struct extobj_spec *extobj_spec = &s->extobjs[i]; 2239 2240 fprintf(f, "\t[%d] = {\n", i); 2241 fprintf(f, "\t\t.name = \"%s\",\n", extobj_spec->name); 2242 fprintf(f, "\t\t.extern_type_name = \"%s\",\n", extobj_spec->extern_type_name); 2243 if (extobj_spec->pragma) 2244 fprintf(f, "\t\t.pragma = \"%s\",\n", extobj_spec->pragma); 2245 else 2246 fprintf(f, "\t\t.pragma = NULL,\n"); 2247 fprintf(f, "\t},\n"); 2248 } 2249 2250 fprintf(f, "};\n\n"); 2251 2252 /* regarray. */ 2253 fprintf(f, "static struct regarray_spec regarrays[] = {\n"); 2254 2255 for (i = 0; i < s->n_regarrays; i++) { 2256 struct regarray_spec *regarray_spec = &s->regarrays[i]; 2257 2258 fprintf(f, "\t[%d] = {\n", i); 2259 fprintf(f, "\t\t.name = \"%s\",\n", regarray_spec->name); 2260 fprintf(f, "\t\t.init_val = %" PRIu64 ",\n", regarray_spec->init_val); 2261 fprintf(f, "\t\t.size = %u,\n", regarray_spec->size); 2262 fprintf(f, "\t},\n"); 2263 } 2264 2265 fprintf(f, "};\n\n"); 2266 2267 /* metarray. */ 2268 fprintf(f, "static struct metarray_spec metarrays[] = {\n"); 2269 2270 for (i = 0; i < s->n_metarrays; i++) { 2271 struct metarray_spec *metarray_spec = &s->metarrays[i]; 2272 2273 fprintf(f, "\t[%d] = {\n", i); 2274 fprintf(f, "\t\t.name = \"%s\",\n", metarray_spec->name); 2275 fprintf(f, "\t\t.size = %u,\n", metarray_spec->size); 2276 fprintf(f, "\t},\n"); 2277 } 2278 2279 fprintf(f, "};\n\n"); 2280 2281 /* rss. */ 2282 fprintf(f, "static struct rss_spec rss[] = {\n"); 2283 2284 for (i = 0; i < s->n_rss; i++) { 2285 struct rss_spec *rss_spec = &s->rss[i]; 2286 fprintf(f, "\t[%d] = {\n", i); 2287 fprintf(f, "\t\t.name = \"%s\",\n", rss_spec->name); 2288 fprintf(f, "\t},\n"); 2289 } 2290 fprintf(f, "};\n\n"); 2291 2292 /* struct. */ 2293 for (i = 0; i < s->n_structs; i++) { 2294 struct struct_spec *struct_spec = &s->structs[i]; 2295 uint32_t j; 2296 2297 fprintf(f, "static struct rte_swx_field_params struct_%s_fields[] = {\n", 2298 struct_spec->name); 2299 2300 for (j = 0; j < struct_spec->n_fields; j++) { 2301 struct rte_swx_field_params *field = &struct_spec->fields[j]; 2302 2303 fprintf(f, "\t[%d] = {\n", j); 2304 fprintf(f, "\t\t.name = \"%s\",\n", field->name); 2305 fprintf(f, "\t\t.n_bits = %u,\n", field->n_bits); 2306 fprintf(f, "\t},\n"); 2307 } 2308 2309 fprintf(f, "};\n\n"); 2310 } 2311 2312 fprintf(f, "static struct struct_spec structs[] = {\n"); 2313 2314 for (i = 0; i < s->n_structs; i++) { 2315 struct struct_spec *struct_spec = &s->structs[i]; 2316 2317 fprintf(f, "\t[%d] = {\n", i); 2318 fprintf(f, "\t\t.name = \"%s\",\n", struct_spec->name); 2319 fprintf(f, "\t\t.fields = struct_%s_fields,\n", struct_spec->name); 2320 fprintf(f, "\t\t.n_fields = " 2321 "sizeof(struct_%s_fields) / sizeof(struct_%s_fields[0]),\n", 2322 struct_spec->name, 2323 struct_spec->name); 2324 fprintf(f, "\t\t.varbit = %d,\n", struct_spec->varbit); 2325 fprintf(f, "\t},\n"); 2326 } 2327 2328 fprintf(f, "};\n\n"); 2329 2330 /* header. */ 2331 fprintf(f, "static struct header_spec headers[] = {\n"); 2332 2333 for (i = 0; i < s->n_headers; i++) { 2334 struct header_spec *header_spec = &s->headers[i]; 2335 2336 fprintf(f, "\t[%d] = {\n", i); 2337 fprintf(f, "\t\t.name = \"%s\",\n", header_spec->name); 2338 fprintf(f, "\t\t.struct_type_name = \"%s\",\n", header_spec->struct_type_name); 2339 fprintf(f, "\t},\n"); 2340 } 2341 2342 fprintf(f, "};\n\n"); 2343 2344 /* metadata. */ 2345 fprintf(f, "static struct metadata_spec metadata[] = {\n"); 2346 2347 for (i = 0; i < s->n_metadata; i++) { 2348 struct metadata_spec *metadata_spec = &s->metadata[i]; 2349 2350 fprintf(f, "\t[%d] = {\n", i); 2351 fprintf(f, "\t\t.struct_type_name = \"%s\",\n", metadata_spec->struct_type_name); 2352 fprintf(f, "\t},\n"); 2353 2354 } 2355 2356 fprintf(f, "};\n\n"); 2357 2358 /* action. */ 2359 for (i = 0; i < s->n_actions; i++) { 2360 struct action_spec *action_spec = &s->actions[i]; 2361 uint32_t j; 2362 2363 fprintf(f, "static const char *action_%s_initial_instructions[] = {\n", 2364 action_spec->name); 2365 2366 for (j = 0; j < action_spec->n_instructions; j++) { 2367 const char *instr = action_spec->instructions[j]; 2368 2369 fprintf(f, "\t[%d] = \"%s\",\n", j, instr); 2370 } 2371 2372 fprintf(f, "};\n\n"); 2373 } 2374 2375 fprintf(f, "static struct action_spec actions[] = {\n"); 2376 2377 for (i = 0; i < s->n_actions; i++) { 2378 struct action_spec *action_spec = &s->actions[i]; 2379 2380 fprintf(f, "\t[%d] = {\n", i); 2381 fprintf(f, "\t\t.name = \"%s\",\n", action_spec->name); 2382 2383 if (action_spec->args_struct_type_name) 2384 fprintf(f, "\t\t.args_struct_type_name = \"%s\",\n", 2385 action_spec->args_struct_type_name); 2386 else 2387 fprintf(f, "\t\t.args_struct_type_name = NULL,\n"); 2388 2389 fprintf(f, "\t\t.instructions = action_%s_initial_instructions,\n", 2390 action_spec->name); 2391 fprintf(f, "\t\t.n_instructions = " 2392 "sizeof(action_%s_initial_instructions) / " 2393 "sizeof(action_%s_initial_instructions[0]),\n", 2394 action_spec->name, 2395 action_spec->name); 2396 fprintf(f, "\t},\n"); 2397 } 2398 2399 fprintf(f, "};\n\n"); 2400 2401 /* table. */ 2402 for (i = 0; i < s->n_tables; i++) { 2403 struct table_spec *table_spec = &s->tables[i]; 2404 uint32_t j; 2405 2406 /* fields. */ 2407 if (table_spec->params.fields && table_spec->params.n_fields) { 2408 fprintf(f, "static struct rte_swx_match_field_params " 2409 "table_%s_fields[] = {\n", 2410 table_spec->name); 2411 2412 for (j = 0; j < table_spec->params.n_fields; j++) { 2413 struct rte_swx_match_field_params *field = 2414 &table_spec->params.fields[j]; 2415 2416 fprintf(f, "\t[%d] = {\n", j); 2417 fprintf(f, "\t\t.name = \"%s\",\n", field->name); 2418 fprintf(f, "\t\t.match_type = %s,\n", 2419 match_type_string_get(field->match_type)); 2420 fprintf(f, "\t},\n"); 2421 } 2422 2423 fprintf(f, "};\n\n"); 2424 } 2425 2426 /* action_names. */ 2427 if (table_spec->params.action_names && table_spec->params.n_actions) { 2428 fprintf(f, "static const char *table_%s_action_names[] = {\n", 2429 table_spec->name); 2430 2431 for (j = 0; j < table_spec->params.n_actions; j++) { 2432 const char *action_name = table_spec->params.action_names[j]; 2433 2434 fprintf(f, "\t[%d] = \"%s\",\n", j, action_name); 2435 } 2436 2437 fprintf(f, "};\n\n"); 2438 } 2439 2440 /* action_is_for_table_entries. */ 2441 if (table_spec->params.action_is_for_table_entries && 2442 table_spec->params.n_actions) { 2443 fprintf(f, "static int table_%s_action_is_for_table_entries[] = {\n", 2444 table_spec->name); 2445 2446 for (j = 0; j < table_spec->params.n_actions; j++) { 2447 int value = table_spec->params.action_is_for_table_entries[j]; 2448 2449 fprintf(f, "\t[%d] = %d,\n", j, value); 2450 } 2451 2452 fprintf(f, "};\n\n"); 2453 } 2454 2455 /* action_is_for_default_entry. */ 2456 if (table_spec->params.action_is_for_default_entry && 2457 table_spec->params.n_actions) { 2458 fprintf(f, "static int table_%s_action_is_for_default_entry[] = {\n", 2459 table_spec->name); 2460 2461 for (j = 0; j < table_spec->params.n_actions; j++) { 2462 int value = table_spec->params.action_is_for_default_entry[j]; 2463 2464 fprintf(f, "\t[%d] = %d,\n", j, value); 2465 } 2466 2467 fprintf(f, "};\n\n"); 2468 } 2469 } 2470 2471 fprintf(f, "static struct table_spec tables[] = {\n"); 2472 2473 for (i = 0; i < s->n_tables; i++) { 2474 struct table_spec *table_spec = &s->tables[i]; 2475 2476 fprintf(f, "\t[%d] = {\n", i); 2477 fprintf(f, "\t\t.name = \"%s\",\n", table_spec->name); 2478 2479 fprintf(f, "\t\t.params = {\n"); 2480 2481 if (table_spec->params.fields && table_spec->params.n_fields) { 2482 fprintf(f, "\t\t\t.fields = table_%s_fields,\n", table_spec->name); 2483 fprintf(f, "\t\t\t.n_fields = " 2484 "sizeof(table_%s_fields) / sizeof(table_%s_fields[0]),\n", 2485 table_spec->name, 2486 table_spec->name); 2487 } else { 2488 fprintf(f, "\t\t\t.fields = NULL,\n"); 2489 fprintf(f, "\t\t\t.n_fields = 0,\n"); 2490 } 2491 2492 if (table_spec->params.action_names && table_spec->params.n_actions) 2493 fprintf(f, "\t\t\t.action_names = table_%s_action_names,\n", 2494 table_spec->name); 2495 else 2496 fprintf(f, "\t\t\t.action_names = NULL,\n"); 2497 2498 if (table_spec->params.action_is_for_table_entries && table_spec->params.n_actions) 2499 fprintf(f, "\t\t\t.action_is_for_table_entries = " 2500 "table_%s_action_is_for_table_entries,\n", 2501 table_spec->name); 2502 else 2503 fprintf(f, "\t\t\t.action_is_for_table_entries = NULL,\n"); 2504 2505 if (table_spec->params.action_is_for_default_entry && table_spec->params.n_actions) 2506 fprintf(f, "\t\t\t.action_is_for_default_entry = " 2507 "table_%s_action_is_for_default_entry,\n", 2508 table_spec->name); 2509 else 2510 fprintf(f, "\t\t\t.action_is_for_default_entry = NULL,\n"); 2511 2512 if (table_spec->params.n_actions) 2513 fprintf(f, "\t\t\t.n_actions = sizeof(table_%s_action_names) / " 2514 "sizeof(table_%s_action_names[0]),\n", 2515 table_spec->name, 2516 table_spec->name); 2517 else 2518 fprintf(f, "\t\t\t.n_actions = 0,\n"); 2519 2520 if (table_spec->params.default_action_name) 2521 fprintf(f, "\t\t\t.default_action_name = \"%s\",\n", 2522 table_spec->params.default_action_name); 2523 else 2524 fprintf(f, "\t\t\t.default_action_name = NULL,\n"); 2525 2526 if (table_spec->params.default_action_args) 2527 fprintf(f, "\t\t\t.default_action_args = \"%s\",\n", 2528 table_spec->params.default_action_args); 2529 else 2530 fprintf(f, "\t\t\t.default_action_args = NULL,\n"); 2531 2532 fprintf(f, "\t\t\t.default_action_is_const = %d,\n", 2533 table_spec->params.default_action_is_const); 2534 2535 if (table_spec->params.hash_func_name) 2536 fprintf(f, "\t\t\t.hash_func_name = \"%s\",\n", 2537 table_spec->params.hash_func_name); 2538 else 2539 fprintf(f, "\t\t\t.hash_func_name = NULL,\n"); 2540 2541 fprintf(f, "\t\t},\n"); 2542 2543 if (table_spec->recommended_table_type_name) 2544 fprintf(f, "\t\t.recommended_table_type_name = \"%s\",\n", 2545 table_spec->recommended_table_type_name); 2546 else 2547 fprintf(f, "\t\t.recommended_table_type_name = NULL,\n"); 2548 2549 if (table_spec->args) 2550 fprintf(f, "\t\t.args = \"%s\",\n", table_spec->args); 2551 else 2552 fprintf(f, "\t\t.args = NULL,\n"); 2553 2554 fprintf(f, "\t\t.size = %u,\n", table_spec->size); 2555 2556 fprintf(f, "\t},\n"); 2557 } 2558 2559 fprintf(f, "};\n\n"); 2560 2561 /* selector. */ 2562 for (i = 0; i < s->n_selectors; i++) { 2563 struct selector_spec *selector_spec = &s->selectors[i]; 2564 uint32_t j; 2565 2566 if (selector_spec->params.selector_field_names && 2567 selector_spec->params.n_selector_fields) { 2568 fprintf(f, "static const char *selector_%s_field_names[] = {\n", 2569 selector_spec->name); 2570 2571 for (j = 0; j < selector_spec->params.n_selector_fields; j++) { 2572 const char *field_name = 2573 selector_spec->params.selector_field_names[j]; 2574 2575 fprintf(f, "\t[%d] = \"%s\",\n", j, field_name); 2576 } 2577 2578 fprintf(f, "};\n\n"); 2579 } 2580 } 2581 2582 fprintf(f, "static struct selector_spec selectors[] = {\n"); 2583 2584 for (i = 0; i < s->n_selectors; i++) { 2585 struct selector_spec *selector_spec = &s->selectors[i]; 2586 2587 fprintf(f, "\t[%d] = {\n", i); 2588 2589 fprintf(f, "\t\t.name = \"%s\",\n", selector_spec->name); 2590 fprintf(f, "\t\t.params = {\n"); 2591 2592 if (selector_spec->params.group_id_field_name) 2593 fprintf(f, "\t\t\t.group_id_field_name = \"%s\",\n", 2594 selector_spec->params.group_id_field_name); 2595 else 2596 fprintf(f, "\t\t\t.group_id_field_name = NULL,\n"); 2597 2598 if (selector_spec->params.selector_field_names && 2599 selector_spec->params.n_selector_fields) { 2600 fprintf(f, "\t\t\t.selector_field_names = selector_%s_field_names,\n", 2601 selector_spec->name); 2602 fprintf(f, "\t\t\t.n_selector_fields = " 2603 "sizeof(selector_%s_field_names) / sizeof(selector_%s_field_names[0]),\n", 2604 selector_spec->name, 2605 selector_spec->name); 2606 } else { 2607 fprintf(f, "\t\t\t.selector_field_names = NULL,\n"); 2608 fprintf(f, "\t\t\t.n_selector_fields = 0,\n"); 2609 } 2610 2611 if (selector_spec->params.member_id_field_name) 2612 fprintf(f, "\t\t\t.member_id_field_name = \"%s\",\n", 2613 selector_spec->params.member_id_field_name); 2614 else 2615 fprintf(f, "\t\t\t.member_id_field_name = NULL,\n"); 2616 2617 fprintf(f, "\t\t\t.n_groups_max = %u,\n", selector_spec->params.n_groups_max); 2618 2619 fprintf(f, "\t\t\t.n_members_per_group_max = %u,\n", 2620 selector_spec->params.n_members_per_group_max); 2621 2622 fprintf(f, "\t\t},\n"); 2623 fprintf(f, "\t},\n"); 2624 } 2625 2626 fprintf(f, "};\n\n"); 2627 2628 /* learner. */ 2629 for (i = 0; i < s->n_learners; i++) { 2630 struct learner_spec *learner_spec = &s->learners[i]; 2631 uint32_t j; 2632 2633 /* field_names. */ 2634 if (learner_spec->params.field_names && learner_spec->params.n_fields) { 2635 fprintf(f, "static const char *learner_%s_field_names[] = {\n", 2636 learner_spec->name); 2637 2638 for (j = 0; j < learner_spec->params.n_fields; j++) { 2639 const char *field_name = learner_spec->params.field_names[j]; 2640 2641 fprintf(f, "\t[%d] = \"%s\",\n", j, field_name); 2642 } 2643 2644 fprintf(f, "};\n\n"); 2645 } 2646 2647 /* action_names. */ 2648 if (learner_spec->params.action_names && learner_spec->params.n_actions) { 2649 fprintf(f, "static const char *learner_%s_action_names[] = {\n", 2650 learner_spec->name); 2651 2652 for (j = 0; j < learner_spec->params.n_actions; j++) { 2653 const char *action_name = learner_spec->params.action_names[j]; 2654 2655 fprintf(f, "\t[%d] = \"%s\",\n", j, action_name); 2656 } 2657 2658 fprintf(f, "};\n\n"); 2659 } 2660 2661 /* action_is_for_table_entries. */ 2662 if (learner_spec->params.action_is_for_table_entries && 2663 learner_spec->params.n_actions) { 2664 fprintf(f, "static int learner_%s_action_is_for_table_entries[] = {\n", 2665 learner_spec->name); 2666 2667 for (j = 0; j < learner_spec->params.n_actions; j++) { 2668 int value = learner_spec->params.action_is_for_table_entries[j]; 2669 2670 fprintf(f, "\t[%d] = %d,\n", j, value); 2671 } 2672 2673 fprintf(f, "};\n\n"); 2674 } 2675 2676 /* action_is_for_default_entry. */ 2677 if (learner_spec->params.action_is_for_default_entry && 2678 learner_spec->params.n_actions) { 2679 fprintf(f, "static int learner_%s_action_is_for_default_entry[] = {\n", 2680 learner_spec->name); 2681 2682 for (j = 0; j < learner_spec->params.n_actions; j++) { 2683 int value = learner_spec->params.action_is_for_default_entry[j]; 2684 2685 fprintf(f, "\t[%d] = %d,\n", j, value); 2686 } 2687 2688 fprintf(f, "};\n\n"); 2689 } 2690 2691 /* timeout. */ 2692 if (learner_spec->timeout && learner_spec->n_timeouts) { 2693 fprintf(f, "static uint32_t learner_%s_timeout[] = {\n", 2694 learner_spec->name); 2695 2696 for (j = 0; j < learner_spec->n_timeouts; j++) { 2697 uint32_t value = learner_spec->timeout[j]; 2698 2699 fprintf(f, "\t[%d] = %u,\n", j, value); 2700 } 2701 2702 fprintf(f, "};\n\n"); 2703 } 2704 } 2705 2706 fprintf(f, "static struct learner_spec learners[] = {\n"); 2707 2708 for (i = 0; i < s->n_learners; i++) { 2709 struct learner_spec *learner_spec = &s->learners[i]; 2710 2711 fprintf(f, "\t[%d] = {\n", i); 2712 fprintf(f, "\t\t.name = \"%s\",\n", learner_spec->name); 2713 2714 fprintf(f, "\t\t.params = {\n"); 2715 2716 if (learner_spec->params.field_names && learner_spec->params.n_fields) { 2717 fprintf(f, "\t\t\t.field_names = learner_%s_field_names,\n", 2718 learner_spec->name); 2719 fprintf(f, "\t\t\t.n_fields = " 2720 "sizeof(learner_%s_field_names) / " 2721 "sizeof(learner_%s_field_names[0]),\n", 2722 learner_spec->name, 2723 learner_spec->name); 2724 } else { 2725 fprintf(f, "\t\t\t.field_names = NULL,\n"); 2726 fprintf(f, "\t\t\t.n_fields = 0,\n"); 2727 } 2728 2729 if (learner_spec->params.action_names && learner_spec->params.n_actions) 2730 fprintf(f, "\t\t\t.action_names = learner_%s_action_names,\n", 2731 learner_spec->name); 2732 else 2733 fprintf(f, "\t\t\t.action_names = NULL,\n"); 2734 2735 if (learner_spec->params.action_is_for_table_entries && 2736 learner_spec->params.n_actions) 2737 fprintf(f, "\t\t\t.action_is_for_table_entries = " 2738 "learner_%s_action_is_for_table_entries,\n", 2739 learner_spec->name); 2740 else 2741 fprintf(f, "\t\t\t.action_is_for_table_entries = NULL,\n"); 2742 2743 if (learner_spec->params.action_is_for_default_entry && 2744 learner_spec->params.n_actions) 2745 fprintf(f, "\t\t\t.action_is_for_default_entry = " 2746 "learner_%s_action_is_for_default_entry,\n", 2747 learner_spec->name); 2748 else 2749 fprintf(f, "\t\t\t.action_is_for_default_entry = NULL,\n"); 2750 2751 if (learner_spec->params.action_names && learner_spec->params.n_actions) 2752 fprintf(f, "\t\t\t.n_actions = " 2753 "sizeof(learner_%s_action_names) / sizeof(learner_%s_action_names[0]),\n", 2754 learner_spec->name, 2755 learner_spec->name); 2756 else 2757 fprintf(f, "\t\t\t.n_actions = NULL,\n"); 2758 2759 if (learner_spec->params.default_action_name) 2760 fprintf(f, "\t\t\t.default_action_name = \"%s\",\n", 2761 learner_spec->params.default_action_name); 2762 else 2763 fprintf(f, "\t\t\t.default_action_name = NULL,\n"); 2764 2765 if (learner_spec->params.default_action_args) 2766 fprintf(f, "\t\t\t.default_action_args = \"%s\",\n", 2767 learner_spec->params.default_action_args); 2768 else 2769 fprintf(f, "\t\t\t.default_action_args = NULL,\n"); 2770 2771 fprintf(f, "\t\t\t.default_action_is_const = %d,\n", 2772 learner_spec->params.default_action_is_const); 2773 2774 if (learner_spec->params.hash_func_name) 2775 fprintf(f, "\t\t\t.hash_func_name = \"%s\",\n", 2776 learner_spec->params.hash_func_name); 2777 else 2778 fprintf(f, "\t\t\t.hash_func_name = NULL,\n"); 2779 2780 fprintf(f, "\t\t},\n"); 2781 2782 fprintf(f, "\t\t.size = %u,\n", learner_spec->size); 2783 2784 if (learner_spec->timeout && learner_spec->n_timeouts) { 2785 fprintf(f, "\t\t.timeout = learner_%s_timeout,\n", learner_spec->name); 2786 fprintf(f, "\t\t\t.n_timeouts = " 2787 "sizeof(learner_%s_timeout) / sizeof(learner_%s_timeout[0]),\n", 2788 learner_spec->name, 2789 learner_spec->name); 2790 } else { 2791 fprintf(f, "\t\t.timeout = NULL,\n"); 2792 fprintf(f, "\t\t\t.n_timeouts = 0,\n"); 2793 } 2794 2795 fprintf(f, "\t},\n"); 2796 } 2797 2798 fprintf(f, "};\n\n"); 2799 2800 /* apply. */ 2801 for (i = 0; i < s->n_apply; i++) { 2802 struct apply_spec *apply_spec = &s->apply[i]; 2803 uint32_t j; 2804 2805 fprintf(f, "static const char *apply%u_initial_instructions[] = {\n", i); 2806 2807 for (j = 0; j < apply_spec->n_instructions; j++) { 2808 const char *instr = apply_spec->instructions[j]; 2809 2810 fprintf(f, "\t[%d] = \"%s\",\n", j, instr); 2811 } 2812 2813 fprintf(f, "};\n\n"); 2814 } 2815 2816 fprintf(f, "static struct apply_spec apply[] = {\n"); 2817 2818 for (i = 0; i < s->n_apply; i++) { 2819 fprintf(f, "\t[%d] = {\n", i); 2820 fprintf(f, "\t.instructions = apply%u_initial_instructions,\n", i); 2821 fprintf(f, "\t.n_instructions = " 2822 "sizeof(apply%u_initial_instructions) / " 2823 "sizeof(apply%u_initial_instructions[0]),\n", 2824 i, 2825 i); 2826 fprintf(f, "\t},\n"); 2827 } 2828 2829 fprintf(f, "};\n\n"); 2830 2831 /* pipeline. */ 2832 fprintf(f, "struct pipeline_spec pipeline_spec = {\n"); 2833 fprintf(f, "\t.extobjs = extobjs,\n"); 2834 fprintf(f, "\t.structs = structs,\n"); 2835 fprintf(f, "\t.headers = headers,\n"); 2836 fprintf(f, "\t.metadata = metadata,\n"); 2837 fprintf(f, "\t.actions = actions,\n"); 2838 fprintf(f, "\t.tables = tables,\n"); 2839 fprintf(f, "\t.selectors = selectors,\n"); 2840 fprintf(f, "\t.learners = learners,\n"); 2841 fprintf(f, "\t.regarrays = regarrays,\n"); 2842 fprintf(f, "\t.metarrays = metarrays,\n"); 2843 fprintf(f, "\t.rss = rss,\n"); 2844 fprintf(f, "\t.apply = apply,\n"); 2845 fprintf(f, "\t.n_extobjs = sizeof(extobjs) / sizeof(extobjs[0]),\n"); 2846 fprintf(f, "\t.n_structs = sizeof(structs) / sizeof(structs[0]),\n"); 2847 fprintf(f, "\t.n_headers = sizeof(headers) / sizeof(headers[0]),\n"); 2848 fprintf(f, "\t.n_metadata = sizeof(metadata) / sizeof(metadata[0]),\n"); 2849 fprintf(f, "\t.n_actions = sizeof(actions) / sizeof(actions[0]),\n"); 2850 fprintf(f, "\t.n_tables = sizeof(tables) / sizeof(tables[0]),\n"); 2851 fprintf(f, "\t.n_selectors = sizeof(selectors) / sizeof(selectors[0]),\n"); 2852 fprintf(f, "\t.n_learners = sizeof(learners) / sizeof(learners[0]),\n"); 2853 fprintf(f, "\t.n_regarrays = sizeof(regarrays) / sizeof(regarrays[0]),\n"); 2854 fprintf(f, "\t.n_metarrays = sizeof(metarrays) / sizeof(metarrays[0]),\n"); 2855 fprintf(f, "\t.n_rss = sizeof(rss) / sizeof(rss[0]),\n"); 2856 fprintf(f, "\t.n_apply = sizeof(apply) / sizeof(apply[0]),\n"); 2857 fprintf(f, "};\n"); 2858 } 2859 2860 struct pipeline_spec * 2861 pipeline_spec_parse(FILE *spec, 2862 uint32_t *err_line, 2863 const char **err_msg) 2864 { 2865 struct extobj_spec extobj_spec = {0}; 2866 struct struct_spec struct_spec = {0}; 2867 struct header_spec header_spec = {0}; 2868 struct metadata_spec metadata_spec = {0}; 2869 struct action_spec action_spec = {0}; 2870 struct table_spec table_spec = {0}; 2871 struct selector_spec selector_spec = {0}; 2872 struct learner_spec learner_spec = {0}; 2873 struct regarray_spec regarray_spec = {0}; 2874 struct metarray_spec metarray_spec = {0}; 2875 struct rss_spec rss_spec = {0}; 2876 struct apply_spec apply_spec = {0}; 2877 struct pipeline_spec *s = NULL; 2878 uint32_t n_lines = 0; 2879 uint32_t block_mask = 0; 2880 int status = 0; 2881 2882 /* Check the input arguments. */ 2883 if (!spec) { 2884 if (err_line) 2885 *err_line = n_lines; 2886 if (err_msg) 2887 *err_msg = "Invalid input argument."; 2888 status = -EINVAL; 2889 goto error; 2890 } 2891 2892 /* Memory allocation. */ 2893 s = calloc(1, sizeof(struct pipeline_spec)); 2894 if (!s) { 2895 if (err_line) 2896 *err_line = n_lines; 2897 if (err_msg) 2898 *err_msg = "Memory allocation failed."; 2899 status = -ENOMEM; 2900 goto error; 2901 } 2902 2903 for (n_lines = 1; ; n_lines++) { 2904 char line[MAX_LINE_LENGTH]; 2905 char *tokens[MAX_TOKENS], *ptr = line; 2906 uint32_t n_tokens = 0; 2907 2908 /* Read next line. */ 2909 if (!fgets(line, sizeof(line), spec)) 2910 break; 2911 2912 /* Parse the line into tokens. */ 2913 for ( ; ; ) { 2914 char *token; 2915 2916 /* Get token. */ 2917 token = strtok_r(ptr, " \f\n\r\t\v", &ptr); 2918 if (!token) 2919 break; 2920 2921 /* Handle comments. */ 2922 if ((token[0] == '#') || 2923 (token[0] == ';') || 2924 ((token[0] == '/') && (token[1] == '/'))) { 2925 break; 2926 } 2927 2928 /* Handle excessively long lines. */ 2929 if (n_tokens >= RTE_DIM(tokens)) { 2930 if (err_line) 2931 *err_line = n_lines; 2932 if (err_msg) 2933 *err_msg = "Too many tokens."; 2934 status = -EINVAL; 2935 goto error; 2936 } 2937 2938 /* Handle excessively long tokens. */ 2939 if (strnlen(token, RTE_SWX_NAME_SIZE) >= 2940 RTE_SWX_NAME_SIZE) { 2941 if (err_line) 2942 *err_line = n_lines; 2943 if (err_msg) 2944 *err_msg = "Token too big."; 2945 status = -EINVAL; 2946 goto error; 2947 } 2948 2949 /* Save token. */ 2950 tokens[n_tokens] = token; 2951 n_tokens++; 2952 } 2953 2954 /* Handle empty lines. */ 2955 if (!n_tokens) 2956 continue; 2957 2958 /* struct block. */ 2959 if (block_mask & (1 << STRUCT_BLOCK)) { 2960 struct struct_spec *new_structs; 2961 2962 status = struct_block_parse(&struct_spec, 2963 &block_mask, 2964 tokens, 2965 n_tokens, 2966 n_lines, 2967 err_line, 2968 err_msg); 2969 if (status) 2970 goto error; 2971 2972 if (block_mask & (1 << STRUCT_BLOCK)) 2973 continue; 2974 2975 /* End of block. */ 2976 new_structs = realloc(s->structs, 2977 (s->n_structs + 1) * sizeof(struct struct_spec)); 2978 if (!new_structs) { 2979 if (err_line) 2980 *err_line = n_lines; 2981 if (err_msg) 2982 *err_msg = "Memory allocation failed."; 2983 status = -ENOMEM; 2984 goto error; 2985 } 2986 2987 s->structs = new_structs; 2988 memcpy(&s->structs[s->n_structs], &struct_spec, sizeof(struct struct_spec)); 2989 s->n_structs++; 2990 memset(&struct_spec, 0, sizeof(struct struct_spec)); 2991 2992 continue; 2993 } 2994 2995 /* action block. */ 2996 if (block_mask & (1 << ACTION_BLOCK)) { 2997 struct action_spec *new_actions; 2998 2999 status = action_block_parse(&action_spec, 3000 &block_mask, 3001 tokens, 3002 n_tokens, 3003 n_lines, 3004 err_line, 3005 err_msg); 3006 if (status) 3007 goto error; 3008 3009 if (block_mask & (1 << ACTION_BLOCK)) 3010 continue; 3011 3012 /* End of block. */ 3013 new_actions = realloc(s->actions, 3014 (s->n_actions + 1) * sizeof(struct action_spec)); 3015 if (!new_actions) { 3016 if (err_line) 3017 *err_line = n_lines; 3018 if (err_msg) 3019 *err_msg = "Memory allocation failed."; 3020 status = -ENOMEM; 3021 goto error; 3022 } 3023 3024 s->actions = new_actions; 3025 memcpy(&s->actions[s->n_actions], &action_spec, sizeof(struct action_spec)); 3026 s->n_actions++; 3027 memset(&action_spec, 0, sizeof(struct action_spec)); 3028 3029 continue; 3030 } 3031 3032 /* table block. */ 3033 if (block_mask & (1 << TABLE_BLOCK)) { 3034 struct table_spec *new_tables; 3035 3036 status = table_block_parse(&table_spec, 3037 &block_mask, 3038 tokens, 3039 n_tokens, 3040 n_lines, 3041 err_line, 3042 err_msg); 3043 if (status) 3044 goto error; 3045 3046 if (block_mask & (1 << TABLE_BLOCK)) 3047 continue; 3048 3049 /* End of block. */ 3050 new_tables = realloc(s->tables, 3051 (s->n_tables + 1) * sizeof(struct table_spec)); 3052 if (!new_tables) { 3053 if (err_line) 3054 *err_line = n_lines; 3055 if (err_msg) 3056 *err_msg = "Memory allocation failed."; 3057 status = -ENOMEM; 3058 goto error; 3059 } 3060 3061 s->tables = new_tables; 3062 memcpy(&s->tables[s->n_tables], &table_spec, sizeof(struct table_spec)); 3063 s->n_tables++; 3064 memset(&table_spec, 0, sizeof(struct table_spec)); 3065 3066 continue; 3067 } 3068 3069 /* selector block. */ 3070 if (block_mask & (1 << SELECTOR_BLOCK)) { 3071 struct selector_spec *new_selectors; 3072 3073 status = selector_block_parse(&selector_spec, 3074 &block_mask, 3075 tokens, 3076 n_tokens, 3077 n_lines, 3078 err_line, 3079 err_msg); 3080 if (status) 3081 goto error; 3082 3083 if (block_mask & (1 << SELECTOR_BLOCK)) 3084 continue; 3085 3086 /* End of block. */ 3087 new_selectors = realloc(s->selectors, 3088 (s->n_selectors + 1) * sizeof(struct selector_spec)); 3089 if (!new_selectors) { 3090 if (err_line) 3091 *err_line = n_lines; 3092 if (err_msg) 3093 *err_msg = "Memory allocation failed."; 3094 status = -ENOMEM; 3095 goto error; 3096 } 3097 3098 s->selectors = new_selectors; 3099 memcpy(&s->selectors[s->n_selectors], 3100 &selector_spec, 3101 sizeof(struct selector_spec)); 3102 s->n_selectors++; 3103 memset(&selector_spec, 0, sizeof(struct selector_spec)); 3104 3105 continue; 3106 } 3107 3108 /* learner block. */ 3109 if (block_mask & (1 << LEARNER_BLOCK)) { 3110 struct learner_spec *new_learners; 3111 3112 status = learner_block_parse(&learner_spec, 3113 &block_mask, 3114 tokens, 3115 n_tokens, 3116 n_lines, 3117 err_line, 3118 err_msg); 3119 if (status) 3120 goto error; 3121 3122 if (block_mask & (1 << LEARNER_BLOCK)) 3123 continue; 3124 3125 /* End of block. */ 3126 new_learners = realloc(s->learners, 3127 (s->n_learners + 1) * sizeof(struct learner_spec)); 3128 if (!new_learners) { 3129 if (err_line) 3130 *err_line = n_lines; 3131 if (err_msg) 3132 *err_msg = "Memory allocation failed."; 3133 status = -ENOMEM; 3134 goto error; 3135 } 3136 3137 s->learners = new_learners; 3138 memcpy(&s->learners[s->n_learners], 3139 &learner_spec, 3140 sizeof(struct learner_spec)); 3141 s->n_learners++; 3142 memset(&learner_spec, 0, sizeof(struct learner_spec)); 3143 3144 continue; 3145 } 3146 3147 /* apply block. */ 3148 if (block_mask & (1 << APPLY_BLOCK)) { 3149 struct apply_spec *new_apply; 3150 3151 status = apply_block_parse(&apply_spec, 3152 &block_mask, 3153 tokens, 3154 n_tokens, 3155 n_lines, 3156 err_line, 3157 err_msg); 3158 if (status) 3159 goto error; 3160 3161 if (block_mask & (1 << APPLY_BLOCK)) 3162 continue; 3163 3164 /* End of block. */ 3165 new_apply = realloc(s->apply, (s->n_apply + 1) * sizeof(struct apply_spec)); 3166 if (!new_apply) { 3167 if (err_line) 3168 *err_line = n_lines; 3169 if (err_msg) 3170 *err_msg = "Memory allocation failed."; 3171 status = -ENOMEM; 3172 goto error; 3173 } 3174 3175 s->apply = new_apply; 3176 memcpy(&s->apply[s->n_apply], &apply_spec, sizeof(struct apply_spec)); 3177 s->n_apply++; 3178 memset(&apply_spec, 0, sizeof(struct apply_spec)); 3179 3180 continue; 3181 } 3182 3183 /* extobj. */ 3184 if (!strcmp(tokens[0], "extobj")) { 3185 struct extobj_spec *new_extobjs; 3186 3187 status = extobj_statement_parse(&extobj_spec, 3188 tokens, 3189 n_tokens, 3190 n_lines, 3191 err_line, 3192 err_msg); 3193 if (status) 3194 goto error; 3195 3196 new_extobjs = realloc(s->extobjs, 3197 (s->n_extobjs + 1) * sizeof(struct extobj_spec)); 3198 if (!new_extobjs) { 3199 if (err_line) 3200 *err_line = n_lines; 3201 if (err_msg) 3202 *err_msg = "Memory allocation failed."; 3203 status = -ENOMEM; 3204 goto error; 3205 } 3206 3207 s->extobjs = new_extobjs; 3208 memcpy(&s->extobjs[s->n_extobjs], &extobj_spec, sizeof(struct extobj_spec)); 3209 s->n_extobjs++; 3210 memset(&extobj_spec, 0, sizeof(struct extobj_spec)); 3211 3212 continue; 3213 } 3214 3215 /* struct. */ 3216 if (!strcmp(tokens[0], "struct")) { 3217 status = struct_statement_parse(&struct_spec, 3218 &block_mask, 3219 tokens, 3220 n_tokens, 3221 n_lines, 3222 err_line, 3223 err_msg); 3224 if (status) 3225 goto error; 3226 3227 continue; 3228 } 3229 3230 /* header. */ 3231 if (!strcmp(tokens[0], "header")) { 3232 struct header_spec *new_headers; 3233 3234 status = header_statement_parse(&header_spec, 3235 tokens, 3236 n_tokens, 3237 n_lines, 3238 err_line, 3239 err_msg); 3240 if (status) 3241 goto error; 3242 3243 new_headers = realloc(s->headers, 3244 (s->n_headers + 1) * sizeof(struct header_spec)); 3245 if (!new_headers) { 3246 if (err_line) 3247 *err_line = n_lines; 3248 if (err_msg) 3249 *err_msg = "Memory allocation failed."; 3250 status = -ENOMEM; 3251 goto error; 3252 } 3253 3254 s->headers = new_headers; 3255 memcpy(&s->headers[s->n_headers], &header_spec, sizeof(struct header_spec)); 3256 s->n_headers++; 3257 memset(&header_spec, 0, sizeof(struct header_spec)); 3258 3259 continue; 3260 } 3261 3262 /* metadata. */ 3263 if (!strcmp(tokens[0], "metadata")) { 3264 struct metadata_spec *new_metadata; 3265 3266 status = metadata_statement_parse(&metadata_spec, 3267 tokens, 3268 n_tokens, 3269 n_lines, 3270 err_line, 3271 err_msg); 3272 if (status) 3273 goto error; 3274 3275 new_metadata = realloc(s->metadata, 3276 (s->n_metadata + 1) * sizeof(struct metadata_spec)); 3277 if (!new_metadata) { 3278 if (err_line) 3279 *err_line = n_lines; 3280 if (err_msg) 3281 *err_msg = "Memory allocation failed."; 3282 status = -ENOMEM; 3283 goto error; 3284 } 3285 3286 s->metadata = new_metadata; 3287 memcpy(&s->metadata[s->n_metadata], 3288 &metadata_spec, 3289 sizeof(struct metadata_spec)); 3290 s->n_metadata++; 3291 memset(&metadata_spec, 0, sizeof(struct metadata_spec)); 3292 3293 continue; 3294 } 3295 3296 /* action. */ 3297 if (!strcmp(tokens[0], "action")) { 3298 status = action_statement_parse(&action_spec, 3299 &block_mask, 3300 tokens, 3301 n_tokens, 3302 n_lines, 3303 err_line, 3304 err_msg); 3305 if (status) 3306 goto error; 3307 3308 continue; 3309 } 3310 3311 /* table. */ 3312 if (!strcmp(tokens[0], "table")) { 3313 status = table_statement_parse(&table_spec, 3314 &block_mask, 3315 tokens, 3316 n_tokens, 3317 n_lines, 3318 err_line, 3319 err_msg); 3320 if (status) 3321 goto error; 3322 3323 continue; 3324 } 3325 3326 /* selector. */ 3327 if (!strcmp(tokens[0], "selector")) { 3328 status = selector_statement_parse(&selector_spec, 3329 &block_mask, 3330 tokens, 3331 n_tokens, 3332 n_lines, 3333 err_line, 3334 err_msg); 3335 if (status) 3336 goto error; 3337 3338 continue; 3339 } 3340 3341 /* learner. */ 3342 if (!strcmp(tokens[0], "learner")) { 3343 status = learner_statement_parse(&learner_spec, 3344 &block_mask, 3345 tokens, 3346 n_tokens, 3347 n_lines, 3348 err_line, 3349 err_msg); 3350 if (status) 3351 goto error; 3352 3353 continue; 3354 } 3355 3356 /* regarray. */ 3357 if (!strcmp(tokens[0], "regarray")) { 3358 struct regarray_spec *new_regarrays; 3359 3360 status = regarray_statement_parse(®array_spec, 3361 tokens, 3362 n_tokens, 3363 n_lines, 3364 err_line, 3365 err_msg); 3366 if (status) 3367 goto error; 3368 3369 new_regarrays = realloc(s->regarrays, 3370 (s->n_regarrays + 1) * sizeof(struct regarray_spec)); 3371 if (!new_regarrays) { 3372 if (err_line) 3373 *err_line = n_lines; 3374 if (err_msg) 3375 *err_msg = "Memory allocation failed."; 3376 status = -ENOMEM; 3377 goto error; 3378 } 3379 3380 s->regarrays = new_regarrays; 3381 memcpy(&s->regarrays[s->n_regarrays], 3382 ®array_spec, 3383 sizeof(struct regarray_spec)); 3384 s->n_regarrays++; 3385 memset(®array_spec, 0, sizeof(struct regarray_spec)); 3386 3387 continue; 3388 } 3389 3390 /* metarray. */ 3391 if (!strcmp(tokens[0], "metarray")) { 3392 struct metarray_spec *new_metarrays; 3393 3394 status = metarray_statement_parse(&metarray_spec, 3395 tokens, 3396 n_tokens, 3397 n_lines, 3398 err_line, 3399 err_msg); 3400 if (status) 3401 goto error; 3402 3403 new_metarrays = realloc(s->metarrays, 3404 (s->n_metarrays + 1) * sizeof(struct metarray_spec)); 3405 if (!new_metarrays) { 3406 if (err_line) 3407 *err_line = n_lines; 3408 if (err_msg) 3409 *err_msg = "Memory allocation failed."; 3410 status = -ENOMEM; 3411 goto error; 3412 } 3413 3414 s->metarrays = new_metarrays; 3415 memcpy(&s->metarrays[s->n_metarrays], 3416 &metarray_spec, 3417 sizeof(struct metarray_spec)); 3418 s->n_metarrays++; 3419 memset(&metarray_spec, 0, sizeof(struct metarray_spec)); 3420 3421 continue; 3422 } 3423 3424 /* rss object configuration */ 3425 if (!strcmp(tokens[0], "rss")) { 3426 struct rss_spec *new_rss; 3427 3428 status = rss_statement_parse(&rss_spec, 3429 tokens, 3430 n_tokens, 3431 n_lines, 3432 err_line, 3433 err_msg); 3434 if (status) 3435 goto error; 3436 3437 new_rss = realloc(s->rss, 3438 (s->n_rss + 1) * sizeof(struct rss_spec)); 3439 if (!new_rss) { 3440 if (err_line) 3441 *err_line = n_lines; 3442 if (err_msg) 3443 *err_msg = "Memory allocation failed."; 3444 status = -ENOMEM; 3445 goto error; 3446 } 3447 3448 s->rss = new_rss; 3449 memcpy(&s->rss[s->n_rss], 3450 &rss_spec, 3451 sizeof(struct rss_spec)); 3452 s->n_rss++; 3453 memset(&rss_spec, 0, sizeof(struct rss_spec)); 3454 3455 continue; 3456 } 3457 3458 /* apply. */ 3459 if (!strcmp(tokens[0], "apply")) { 3460 status = apply_statement_parse(&block_mask, 3461 tokens, 3462 n_tokens, 3463 n_lines, 3464 err_line, 3465 err_msg); 3466 if (status) 3467 goto error; 3468 3469 continue; 3470 } 3471 3472 /* Anything else. */ 3473 if (err_line) 3474 *err_line = n_lines; 3475 if (err_msg) 3476 *err_msg = "Unknown statement."; 3477 status = -EINVAL; 3478 goto error; 3479 } 3480 3481 /* Handle unfinished block. */ 3482 if (block_mask) { 3483 if (err_line) 3484 *err_line = n_lines; 3485 if (err_msg) 3486 *err_msg = "Missing }."; 3487 status = -EINVAL; 3488 goto error; 3489 } 3490 3491 return s; 3492 3493 error: 3494 extobj_spec_free(&extobj_spec); 3495 struct_spec_free(&struct_spec); 3496 header_spec_free(&header_spec); 3497 metadata_spec_free(&metadata_spec); 3498 action_spec_free(&action_spec); 3499 table_spec_free(&table_spec); 3500 selector_spec_free(&selector_spec); 3501 learner_spec_free(&learner_spec); 3502 regarray_spec_free(®array_spec); 3503 metarray_spec_free(&metarray_spec); 3504 rss_spec_free(&rss_spec); 3505 apply_spec_free(&apply_spec); 3506 pipeline_spec_free(s); 3507 3508 return NULL; 3509 } 3510 3511 int 3512 pipeline_spec_configure(struct rte_swx_pipeline *p, 3513 struct pipeline_spec *s, 3514 const char **err_msg) 3515 { 3516 uint32_t i; 3517 int status = 0; 3518 3519 /* extobj. */ 3520 for (i = 0; i < s->n_extobjs; i++) { 3521 struct extobj_spec *extobj_spec = &s->extobjs[i]; 3522 3523 status = rte_swx_pipeline_extern_object_config(p, 3524 extobj_spec->name, 3525 extobj_spec->extern_type_name, 3526 extobj_spec->pragma); 3527 if (status) { 3528 if (err_msg) 3529 *err_msg = "Extern object configuration error."; 3530 return status; 3531 } 3532 } 3533 3534 /* regarray. */ 3535 for (i = 0; i < s->n_regarrays; i++) { 3536 struct regarray_spec *regarray_spec = &s->regarrays[i]; 3537 3538 status = rte_swx_pipeline_regarray_config(p, 3539 regarray_spec->name, 3540 regarray_spec->size, 3541 regarray_spec->init_val); 3542 if (status) { 3543 if (err_msg) 3544 *err_msg = "Register array configuration error."; 3545 return status; 3546 } 3547 } 3548 3549 /* rss. */ 3550 for (i = 0; i < s->n_rss; i++) { 3551 struct rss_spec *rss_spec = &s->rss[i]; 3552 3553 status = rte_swx_pipeline_rss_config(p, rss_spec->name); 3554 if (status) { 3555 if (err_msg) 3556 *err_msg = "rss object configuration error."; 3557 return status; 3558 } 3559 } 3560 3561 /* metarray. */ 3562 for (i = 0; i < s->n_metarrays; i++) { 3563 struct metarray_spec *metarray_spec = &s->metarrays[i]; 3564 3565 status = rte_swx_pipeline_metarray_config(p, 3566 metarray_spec->name, 3567 metarray_spec->size); 3568 if (status) { 3569 if (err_msg) 3570 *err_msg = "Meter array configuration error."; 3571 return status; 3572 } 3573 } 3574 3575 /* struct. */ 3576 for (i = 0; i < s->n_structs; i++) { 3577 struct struct_spec *struct_spec = &s->structs[i]; 3578 3579 status = rte_swx_pipeline_struct_type_register(p, 3580 struct_spec->name, 3581 struct_spec->fields, 3582 struct_spec->n_fields, 3583 struct_spec->varbit); 3584 if (status) { 3585 if (err_msg) 3586 *err_msg = "Struct type registration error."; 3587 return status; 3588 } 3589 } 3590 3591 /* header. */ 3592 for (i = 0; i < s->n_headers; i++) { 3593 struct header_spec *header_spec = &s->headers[i]; 3594 3595 status = rte_swx_pipeline_packet_header_register(p, 3596 header_spec->name, 3597 header_spec->struct_type_name); 3598 if (status) { 3599 if (err_msg) 3600 *err_msg = "Header configuration error."; 3601 return status; 3602 } 3603 } 3604 3605 /* metadata. */ 3606 for (i = 0; i < s->n_metadata; i++) { 3607 struct metadata_spec *metadata_spec = &s->metadata[i]; 3608 3609 status = rte_swx_pipeline_packet_metadata_register(p, 3610 metadata_spec->struct_type_name); 3611 if (status) { 3612 if (err_msg) 3613 *err_msg = "Meta-data registration error."; 3614 return status; 3615 } 3616 } 3617 3618 /* action. */ 3619 for (i = 0; i < s->n_actions; i++) { 3620 struct action_spec *action_spec = &s->actions[i]; 3621 3622 status = rte_swx_pipeline_action_config(p, 3623 action_spec->name, 3624 action_spec->args_struct_type_name, 3625 action_spec->instructions, 3626 action_spec->n_instructions); 3627 if (status) { 3628 if (err_msg) 3629 *err_msg = "Action configuration error."; 3630 return status; 3631 } 3632 } 3633 3634 /* table. */ 3635 for (i = 0; i < s->n_tables; i++) { 3636 struct table_spec *table_spec = &s->tables[i]; 3637 3638 status = rte_swx_pipeline_table_config(p, 3639 table_spec->name, 3640 &table_spec->params, 3641 table_spec->recommended_table_type_name, 3642 table_spec->args, 3643 table_spec->size); 3644 if (status) { 3645 if (err_msg) 3646 *err_msg = "Table configuration error."; 3647 return status; 3648 } 3649 } 3650 3651 /* selector. */ 3652 for (i = 0; i < s->n_selectors; i++) { 3653 struct selector_spec *selector_spec = &s->selectors[i]; 3654 3655 status = rte_swx_pipeline_selector_config(p, 3656 selector_spec->name, 3657 &selector_spec->params); 3658 if (status) { 3659 if (err_msg) 3660 *err_msg = "Selector table configuration error."; 3661 return status; 3662 } 3663 } 3664 3665 /* learner. */ 3666 for (i = 0; i < s->n_learners; i++) { 3667 struct learner_spec *learner_spec = &s->learners[i]; 3668 3669 status = rte_swx_pipeline_learner_config(p, 3670 learner_spec->name, 3671 &learner_spec->params, 3672 learner_spec->size, 3673 learner_spec->timeout, 3674 learner_spec->n_timeouts); 3675 if (status) { 3676 if (err_msg) 3677 *err_msg = "Learner table configuration error."; 3678 return status; 3679 } 3680 } 3681 3682 /* apply. */ 3683 for (i = 0; i < s->n_apply; i++) { 3684 struct apply_spec *apply_spec = &s->apply[i]; 3685 3686 status = rte_swx_pipeline_instructions_config(p, 3687 apply_spec->instructions, 3688 apply_spec->n_instructions); 3689 if (status) { 3690 if (err_msg) 3691 *err_msg = "Pipeline instructions configuration error."; 3692 return status; 3693 } 3694 } 3695 3696 return 0; 3697 } 3698 3699 static void 3700 port_in_params_free(void *params, const char *port_type) 3701 { 3702 uintptr_t dev_name; 3703 3704 if (!params || !port_type) 3705 return; 3706 3707 if (!strcmp(port_type, "ethdev")) { 3708 struct rte_swx_port_ethdev_reader_params *p = params; 3709 3710 dev_name = (uintptr_t)p->dev_name; 3711 } else if (!strcmp(port_type, "ring")) { 3712 struct rte_swx_port_ring_reader_params *p = params; 3713 3714 dev_name = (uintptr_t)p->name; 3715 } else if (!strcmp(port_type, "source")) { 3716 struct rte_swx_port_source_params *p = params; 3717 3718 dev_name = (uintptr_t)p->file_name; 3719 } else 3720 dev_name = (uintptr_t)NULL; 3721 3722 free((void *)dev_name); 3723 free(params); 3724 } 3725 3726 static void 3727 port_out_params_free(void *params, const char *port_type) 3728 { 3729 uintptr_t dev_name; 3730 3731 if (!params || !port_type) 3732 return; 3733 3734 if (!strcmp(port_type, "ethdev")) { 3735 struct rte_swx_port_ethdev_writer_params *p = params; 3736 3737 dev_name = (uintptr_t)p->dev_name; 3738 } else if (!strcmp(port_type, "ring")) { 3739 struct rte_swx_port_ring_writer_params *p = params; 3740 3741 dev_name = (uintptr_t)p->name; 3742 } else if (!strcmp(port_type, "sink")) { 3743 struct rte_swx_port_sink_params *p = params; 3744 3745 dev_name = (uintptr_t)p->file_name; 3746 } else 3747 dev_name = (uintptr_t)NULL; 3748 3749 free((void *)dev_name); 3750 free(params); 3751 } 3752 3753 void 3754 pipeline_iospec_free(struct pipeline_iospec *s) 3755 { 3756 uint32_t i; 3757 3758 if (!s) 3759 return; 3760 3761 /* Input ports. */ 3762 for (i = 0; i < s->n_ports_in; i++) { 3763 uintptr_t name = (uintptr_t)s->port_in_type[i]; 3764 3765 port_in_params_free(s->port_in_params[i], s->port_in_type[i]); 3766 free((void *)name); 3767 } 3768 3769 free(s->port_in_type); 3770 free(s->port_in_params); 3771 3772 /* Output ports. */ 3773 for (i = 0; i < s->n_ports_out; i++) { 3774 uintptr_t name = (uintptr_t)s->port_out_type[i]; 3775 3776 port_out_params_free(s->port_out_params[i], s->port_out_type[i]); 3777 free((void *)name); 3778 } 3779 3780 free(s->port_out_type); 3781 free(s->port_out_params); 3782 3783 free(s); 3784 } 3785 3786 static int 3787 mirroring_parse(struct rte_swx_pipeline_mirroring_params *p, 3788 char **tokens, 3789 uint32_t n_tokens, 3790 const char **err_msg) 3791 { 3792 char *token; 3793 3794 if ((n_tokens != 4) || strcmp(tokens[0], "slots") || strcmp(tokens[2], "sessions")) { 3795 if (err_msg) 3796 *err_msg = "Invalid statement."; 3797 return -EINVAL; 3798 } 3799 3800 /* <n_slots>. */ 3801 token = tokens[1]; 3802 p->n_slots = strtoul(token, &token, 0); 3803 if (token[0]) { 3804 if (err_msg) 3805 *err_msg = "Invalid <n_slots> parameter."; 3806 return -EINVAL; 3807 } 3808 3809 /* <n_sessions>. */ 3810 token = tokens[3]; 3811 p->n_sessions = strtoul(token, &token, 0); 3812 if (token[0]) { 3813 if (err_msg) 3814 *err_msg = "Invalid <n_sessions> parameter."; 3815 return -EINVAL; 3816 } 3817 3818 return 0; 3819 } 3820 3821 static void * 3822 port_in_ethdev_parse(char **tokens, uint32_t n_tokens, const char **err_msg) 3823 { 3824 struct rte_swx_port_ethdev_reader_params *p = NULL; 3825 char *token, *dev_name = NULL; 3826 uint32_t queue_id, burst_size; 3827 3828 if ((n_tokens != 5) || strcmp(tokens[1], "rxq") || strcmp(tokens[3], "bsz")) { 3829 if (err_msg) 3830 *err_msg = "Invalid statement."; 3831 return NULL; 3832 } 3833 3834 /* <queue_id>. */ 3835 token = tokens[2]; 3836 queue_id = strtoul(token, &token, 0); 3837 if (token[0]) { 3838 if (err_msg) 3839 *err_msg = "Invalid <queue_id> parameter."; 3840 return NULL; 3841 } 3842 3843 /* <burst_size>. */ 3844 token = tokens[4]; 3845 burst_size = strtoul(token, &token, 0); 3846 if (token[0]) { 3847 if (err_msg) 3848 *err_msg = "Invalid <burst_size> parameter."; 3849 return NULL; 3850 } 3851 3852 /* Memory allocation. */ 3853 dev_name = strdup(tokens[0]); 3854 p = malloc(sizeof(struct rte_swx_port_ethdev_reader_params)); 3855 if (!dev_name || !p) { 3856 free(dev_name); 3857 free(p); 3858 3859 if (err_msg) 3860 *err_msg = "Memory allocation failed."; 3861 return NULL; 3862 } 3863 3864 /* Initialization. */ 3865 p->dev_name = dev_name; 3866 p->queue_id = queue_id; 3867 p->burst_size = burst_size; 3868 3869 return p; 3870 } 3871 3872 static void * 3873 port_in_ring_parse(char **tokens, uint32_t n_tokens, const char **err_msg) 3874 { 3875 struct rte_swx_port_ring_reader_params *p = NULL; 3876 char *token, *name = NULL; 3877 uint32_t burst_size; 3878 3879 if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) { 3880 if (err_msg) 3881 *err_msg = "Invalid statement."; 3882 return NULL; 3883 } 3884 3885 /* <burst_size>. */ 3886 token = tokens[2]; 3887 burst_size = strtoul(token, &token, 0); 3888 if (token[0]) { 3889 if (err_msg) 3890 *err_msg = "Invalid <burst_size> parameter."; 3891 return NULL; 3892 } 3893 3894 /* Memory allocation. */ 3895 name = strdup(tokens[0]); 3896 p = malloc(sizeof(struct rte_swx_port_ring_reader_params)); 3897 if (!name || !p) { 3898 free(name); 3899 free(p); 3900 3901 if (err_msg) 3902 *err_msg = "Memory allocation failed."; 3903 return NULL; 3904 } 3905 3906 /* Initialization. */ 3907 p->name = name; 3908 p->burst_size = burst_size; 3909 3910 return p; 3911 } 3912 3913 static void * 3914 port_in_source_parse(char **tokens, uint32_t n_tokens, const char **err_msg) 3915 { 3916 struct rte_swx_port_source_params *p = NULL; 3917 struct rte_mempool *pool = NULL; 3918 char *token, *file_name = NULL; 3919 uint32_t n_loops, n_pkts_max; 3920 3921 if ((n_tokens != 8) || 3922 strcmp(tokens[0], "mempool") || 3923 strcmp(tokens[2], "file") || 3924 strcmp(tokens[4], "loop") || 3925 strcmp(tokens[6], "packets")) { 3926 if (err_msg) 3927 *err_msg = "Invalid statement."; 3928 return NULL; 3929 } 3930 3931 /* <mempool_name>. */ 3932 pool = rte_mempool_lookup(tokens[1]); 3933 if (!pool) { 3934 if (err_msg) 3935 *err_msg = "Invalid <mempool_name> parameter."; 3936 return NULL; 3937 } 3938 3939 /* <n_loops>. */ 3940 token = tokens[5]; 3941 n_loops = strtoul(token, &token, 0); 3942 if (token[0]) { 3943 if (err_msg) 3944 *err_msg = "Invalid <n_loops> parameter."; 3945 return NULL; 3946 } 3947 3948 /* <n_pkts_max>. */ 3949 token = tokens[7]; 3950 n_pkts_max = strtoul(token, &token, 0); 3951 if (token[0]) { 3952 if (err_msg) 3953 *err_msg = "Invalid <n_pkts_max> parameter."; 3954 return NULL; 3955 } 3956 3957 /* Memory allocation. */ 3958 file_name = strdup(tokens[3]); 3959 p = malloc(sizeof(struct rte_swx_port_source_params)); 3960 if (!file_name || !p) { 3961 free(file_name); 3962 free(p); 3963 3964 if (err_msg) 3965 *err_msg = "Memory allocation failed."; 3966 return NULL; 3967 } 3968 3969 /* Initialization. */ 3970 p->pool = pool; 3971 p->file_name = file_name; 3972 p->n_loops = n_loops; 3973 p->n_pkts_max = n_pkts_max; 3974 3975 return p; 3976 } 3977 3978 static void * 3979 port_in_fd_parse(char **tokens, 3980 uint32_t n_tokens, 3981 const char **err_msg) 3982 { 3983 struct rte_swx_port_fd_reader_params *p = NULL; 3984 struct rte_mempool *mempool = NULL; 3985 char *token; 3986 uint32_t mtu, burst_size; 3987 int fd; 3988 3989 if ((n_tokens != 7) || 3990 strcmp(tokens[1], "mtu") || 3991 strcmp(tokens[3], "mempool") || 3992 strcmp(tokens[5], "bsz")) { 3993 if (err_msg) 3994 *err_msg = "Invalid statement."; 3995 return NULL; 3996 } 3997 3998 /* <file_descriptor>. */ 3999 token = tokens[0]; 4000 fd = strtol(token, &token, 0); 4001 if (token[0]) { 4002 if (err_msg) 4003 *err_msg = "Invalid <file_descriptor> parameter."; 4004 return NULL; 4005 } 4006 4007 /* <mtu>. */ 4008 token = tokens[2]; 4009 mtu = strtoul(token, &token, 0); 4010 if (token[0]) { 4011 if (err_msg) 4012 *err_msg = "Invalid <mtu> parameter."; 4013 return NULL; 4014 } 4015 4016 /* <mempool_name>. */ 4017 mempool = rte_mempool_lookup(tokens[4]); 4018 if (!mempool) { 4019 if (err_msg) 4020 *err_msg = "Invalid <mempool_name> parameter."; 4021 return NULL; 4022 } 4023 4024 /* <burst_size>. */ 4025 token = tokens[6]; 4026 burst_size = strtoul(token, &token, 0); 4027 if (token[0]) { 4028 if (err_msg) 4029 *err_msg = "Invalid <burst_size> parameter."; 4030 return NULL; 4031 } 4032 4033 /* Memory allocation. */ 4034 p = malloc(sizeof(struct rte_swx_port_fd_reader_params)); 4035 if (!p) { 4036 if (err_msg) 4037 *err_msg = "Memory allocation failed."; 4038 return NULL; 4039 } 4040 4041 /* Initialization. */ 4042 p->fd = fd; 4043 p->mtu = mtu; 4044 p->mempool = mempool; 4045 p->burst_size = burst_size; 4046 4047 return p; 4048 } 4049 4050 static void * 4051 port_out_ethdev_parse(char **tokens, uint32_t n_tokens, const char **err_msg) 4052 { 4053 struct rte_swx_port_ethdev_writer_params *p = NULL; 4054 char *token, *dev_name = NULL; 4055 uint32_t queue_id, burst_size; 4056 4057 if ((n_tokens != 5) || strcmp(tokens[1], "txq") || strcmp(tokens[3], "bsz")) { 4058 if (err_msg) 4059 *err_msg = "Invalid statement."; 4060 return NULL; 4061 } 4062 4063 /* <queue_id>. */ 4064 token = tokens[2]; 4065 queue_id = strtoul(token, &token, 0); 4066 if (token[0]) { 4067 if (err_msg) 4068 *err_msg = "Invalid <queue_id> parameter."; 4069 return NULL; 4070 } 4071 4072 /* <burst_size>. */ 4073 token = tokens[4]; 4074 burst_size = strtoul(token, &token, 0); 4075 if (token[0]) { 4076 if (err_msg) 4077 *err_msg = "Invalid <burst_size> parameter."; 4078 return NULL; 4079 } 4080 4081 /* Memory allocation. */ 4082 dev_name = strdup(tokens[0]); 4083 p = malloc(sizeof(struct rte_swx_port_ethdev_writer_params)); 4084 if (!dev_name || !p) { 4085 free(dev_name); 4086 free(p); 4087 4088 if (err_msg) 4089 *err_msg = "Memory allocation failed."; 4090 return NULL; 4091 } 4092 4093 /* Initialization. */ 4094 p->dev_name = dev_name; 4095 p->queue_id = queue_id; 4096 p->burst_size = burst_size; 4097 4098 return p; 4099 } 4100 4101 static void * 4102 port_out_ring_parse(char **tokens, uint32_t n_tokens, const char **err_msg) 4103 { 4104 struct rte_swx_port_ring_writer_params *p = NULL; 4105 char *token, *name = NULL; 4106 uint32_t burst_size; 4107 4108 if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) { 4109 if (err_msg) 4110 *err_msg = "Invalid statement."; 4111 return NULL; 4112 } 4113 4114 /* <burst_size>. */ 4115 token = tokens[2]; 4116 burst_size = strtoul(token, &token, 0); 4117 if (token[0]) { 4118 if (err_msg) 4119 *err_msg = "Invalid <burst_size> parameter."; 4120 return NULL; 4121 } 4122 4123 /* Memory allocation. */ 4124 name = strdup(tokens[0]); 4125 p = malloc(sizeof(struct rte_swx_port_ring_writer_params)); 4126 if (!name || !p) { 4127 free(name); 4128 free(p); 4129 4130 if (err_msg) 4131 *err_msg = "Memory allocation failed."; 4132 return NULL; 4133 } 4134 4135 /* Initialization. */ 4136 p->name = name; 4137 p->burst_size = burst_size; 4138 4139 return p; 4140 } 4141 4142 static void * 4143 port_out_sink_parse(char **tokens, uint32_t n_tokens, const char **err_msg) 4144 { 4145 struct rte_swx_port_sink_params *p = NULL; 4146 char *file_name = NULL; 4147 int file_name_valid = 0; 4148 4149 if ((n_tokens != 2) || strcmp(tokens[0], "file")) { 4150 if (err_msg) 4151 *err_msg = "Invalid statement."; 4152 return NULL; 4153 } 4154 4155 /* Memory allocation. */ 4156 if (strcmp(tokens[1], "none")) { 4157 file_name_valid = 1; 4158 file_name = strdup(tokens[1]); 4159 } 4160 4161 p = malloc(sizeof(struct rte_swx_port_ring_writer_params)); 4162 if ((file_name_valid && !file_name) || !p) { 4163 free(file_name); 4164 free(p); 4165 4166 if (err_msg) 4167 *err_msg = "Memory allocation failed."; 4168 return NULL; 4169 } 4170 4171 /* Initialization. */ 4172 p->file_name = file_name; 4173 4174 return p; 4175 } 4176 4177 static void * 4178 port_out_fd_parse(char **tokens, 4179 uint32_t n_tokens, 4180 const char **err_msg) 4181 { 4182 struct rte_swx_port_fd_writer_params *p = NULL; 4183 char *token; 4184 uint32_t burst_size; 4185 int fd; 4186 4187 if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) { 4188 if (err_msg) 4189 *err_msg = "Invalid statement."; 4190 return NULL; 4191 } 4192 4193 /* <file_descriptor>. */ 4194 token = tokens[0]; 4195 fd = strtol(token, &token, 0); 4196 if (token[0]) { 4197 if (err_msg) 4198 *err_msg = "Invalid <file_descriptor> parameter."; 4199 return NULL; 4200 } 4201 4202 /* <burst_size>. */ 4203 token = tokens[2]; 4204 burst_size = strtoul(token, &token, 0); 4205 if (token[0]) { 4206 if (err_msg) 4207 *err_msg = "Invalid <burst_size> parameter."; 4208 return NULL; 4209 } 4210 4211 /* Memory allocation. */ 4212 p = malloc(sizeof(struct rte_swx_port_fd_writer_params)); 4213 if (!p) { 4214 if (err_msg) 4215 *err_msg = "Memory allocation failed."; 4216 return NULL; 4217 } 4218 4219 /* Initialization. */ 4220 p->fd = fd; 4221 p->burst_size = burst_size; 4222 4223 return p; 4224 } 4225 4226 struct pipeline_iospec * 4227 pipeline_iospec_parse(FILE *spec, 4228 uint32_t *err_line, 4229 const char **err_msg) 4230 { 4231 struct pipeline_iospec *s = NULL; 4232 uint32_t n_lines = 0; 4233 4234 /* Check the input arguments. */ 4235 if (!spec) { 4236 if (err_line) 4237 *err_line = n_lines; 4238 if (err_msg) 4239 *err_msg = "Invalid input argument."; 4240 goto error; 4241 } 4242 4243 /* Memory allocation. */ 4244 s = calloc(1, sizeof(struct pipeline_iospec)); 4245 if (!s) { 4246 if (err_line) 4247 *err_line = n_lines; 4248 if (err_msg) 4249 *err_msg = "Memory allocation failed."; 4250 goto error; 4251 } 4252 4253 /* Initialize with the default values. */ 4254 s->mirroring_params.n_slots = RTE_SWX_PACKET_MIRRORING_SLOTS_DEFAULT; 4255 s->mirroring_params.n_sessions = RTE_SWX_PACKET_MIRRORING_SESSIONS_DEFAULT; 4256 4257 for (n_lines = 1; ; n_lines++) { 4258 char line[MAX_LINE_LENGTH]; 4259 char *tokens[MAX_TOKENS], *ptr = line; 4260 uint32_t n_tokens = 0; 4261 4262 /* Read next line. */ 4263 if (!fgets(line, sizeof(line), spec)) 4264 break; 4265 4266 /* Parse the line into tokens. */ 4267 for ( ; ; ) { 4268 char *token; 4269 4270 /* Get token. */ 4271 token = strtok_r(ptr, " \f\n\r\t\v", &ptr); 4272 if (!token) 4273 break; 4274 4275 /* Handle comments. */ 4276 if ((token[0] == '#') || 4277 (token[0] == ';') || 4278 ((token[0] == '/') && (token[1] == '/'))) { 4279 break; 4280 } 4281 4282 /* Handle excessively long lines. */ 4283 if (n_tokens >= RTE_DIM(tokens)) { 4284 if (err_line) 4285 *err_line = n_lines; 4286 if (err_msg) 4287 *err_msg = "Too many tokens."; 4288 goto error; 4289 } 4290 4291 /* Handle excessively long tokens. */ 4292 if (strnlen(token, RTE_SWX_NAME_SIZE) >= 4293 RTE_SWX_NAME_SIZE) { 4294 if (err_line) 4295 *err_line = n_lines; 4296 if (err_msg) 4297 *err_msg = "Token too big."; 4298 goto error; 4299 } 4300 4301 /* Save token. */ 4302 tokens[n_tokens] = token; 4303 n_tokens++; 4304 } 4305 4306 /* Handle empty lines. */ 4307 if (!n_tokens) 4308 continue; 4309 4310 /* mirroring. */ 4311 if ((n_tokens >= 1) && !strcmp(tokens[0], "mirroring")) { 4312 int status = 0; 4313 4314 status = mirroring_parse(&s->mirroring_params, 4315 &tokens[1], 4316 n_tokens - 1, 4317 err_msg); 4318 if (status) { 4319 if (err_line) 4320 *err_line = n_lines; 4321 goto error; 4322 } 4323 4324 continue; 4325 } 4326 4327 /* port in. */ 4328 if ((n_tokens >= 4) && !strcmp(tokens[0], "port") && !strcmp(tokens[1], "in")) { 4329 char *token = tokens[2]; 4330 uint32_t *new_id = NULL; 4331 const char **new_type = NULL, *port_type = NULL; 4332 void **new_params = NULL, *p = NULL; 4333 uint32_t port_id; 4334 4335 /* <port_id>. */ 4336 port_id = strtoul(token, &token, 0); 4337 if (token[0]) { 4338 if (err_line) 4339 *err_line = n_lines; 4340 if (err_msg) 4341 *err_msg = "Invalid port ID."; 4342 goto error; 4343 } 4344 4345 /* <port_type>. */ 4346 if (!strcmp(tokens[3], "ethdev")) 4347 p = port_in_ethdev_parse(&tokens[4], n_tokens - 4, err_msg); 4348 else if (!strcmp(tokens[3], "ring")) 4349 p = port_in_ring_parse(&tokens[4], n_tokens - 4, err_msg); 4350 else if (!strcmp(tokens[3], "source")) 4351 p = port_in_source_parse(&tokens[4], n_tokens - 4, err_msg); 4352 else if (!strcmp(tokens[3], "fd")) 4353 p = port_in_fd_parse(&tokens[4], n_tokens - 4, err_msg); 4354 else { 4355 p = NULL; 4356 if (err_msg) 4357 *err_msg = "Invalid port type."; 4358 } 4359 4360 if (!p) { 4361 if (err_line) 4362 *err_line = n_lines; 4363 goto error; 4364 } 4365 4366 /* New port. */ 4367 port_type = strdup(tokens[3]); 4368 new_id = realloc(s->port_in_id, 4369 (s->n_ports_in + 1) * sizeof(uint32_t)); 4370 new_type = realloc(s->port_in_type, 4371 (s->n_ports_in + 1) * sizeof(char *)); 4372 new_params = realloc(s->port_in_params, 4373 (s->n_ports_in + 1) * sizeof(void *)); 4374 if (!port_type || !new_id || !new_type || !new_params) { 4375 uintptr_t pt = (uintptr_t)port_type; 4376 4377 port_in_params_free(p, tokens[3]); 4378 free((void *)pt); 4379 free(new_id); 4380 free(new_type); 4381 free(new_params); 4382 4383 if (err_line) 4384 *err_line = n_lines; 4385 if (err_msg) 4386 *err_msg = "Memory allocation failed."; 4387 goto error; 4388 } 4389 4390 s->port_in_id = new_id; 4391 s->port_in_type = new_type; 4392 s->port_in_params = new_params; 4393 4394 s->port_in_id[s->n_ports_in] = port_id; 4395 s->port_in_type[s->n_ports_in] = port_type; 4396 s->port_in_params[s->n_ports_in] = p; 4397 s->n_ports_in++; 4398 4399 continue; 4400 } 4401 4402 /* port out. */ 4403 if ((n_tokens >= 4) && !strcmp(tokens[0], "port") && !strcmp(tokens[1], "out")) { 4404 char *token = tokens[2]; 4405 uint32_t *new_id = NULL; 4406 const char **new_type = NULL, *port_type = NULL; 4407 void **new_params = NULL, *p = NULL; 4408 uint32_t port_id; 4409 4410 /* <port_id>. */ 4411 port_id = strtoul(token, &token, 0); 4412 if (token[0]) { 4413 if (err_line) 4414 *err_line = n_lines; 4415 if (err_msg) 4416 *err_msg = "Invalid port ID."; 4417 goto error; 4418 } 4419 4420 /* <port_type>. */ 4421 if (!strcmp(tokens[3], "ethdev")) 4422 p = port_out_ethdev_parse(&tokens[4], n_tokens - 4, err_msg); 4423 else if (!strcmp(tokens[3], "ring")) 4424 p = port_out_ring_parse(&tokens[4], n_tokens - 4, err_msg); 4425 else if (!strcmp(tokens[3], "sink")) 4426 p = port_out_sink_parse(&tokens[4], n_tokens - 4, err_msg); 4427 else if (!strcmp(tokens[3], "fd")) 4428 p = port_out_fd_parse(&tokens[4], n_tokens - 4, err_msg); 4429 else { 4430 p = NULL; 4431 if (err_msg) 4432 *err_msg = "Invalid port type."; 4433 } 4434 4435 if (!p) { 4436 if (err_line) 4437 *err_line = n_lines; 4438 goto error; 4439 } 4440 4441 /* New port. */ 4442 port_type = strdup(tokens[3]); 4443 new_id = realloc(s->port_out_id, 4444 (s->n_ports_out + 1) * sizeof(uint32_t)); 4445 new_type = realloc(s->port_out_type, 4446 (s->n_ports_out + 1) * sizeof(char *)); 4447 new_params = realloc(s->port_out_params, 4448 (s->n_ports_out + 1) * sizeof(void *)); 4449 if (!port_type || !new_id || !new_type || !new_params) { 4450 uintptr_t pt = (uintptr_t)port_type; 4451 4452 port_out_params_free(p, tokens[3]); 4453 free((void *)pt); 4454 free(new_id); 4455 free(new_type); 4456 free(new_params); 4457 4458 if (err_line) 4459 *err_line = n_lines; 4460 if (err_msg) 4461 *err_msg = "Memory allocation failed."; 4462 goto error; 4463 } 4464 4465 s->port_out_id = new_id; 4466 s->port_out_type = new_type; 4467 s->port_out_params = new_params; 4468 4469 s->port_out_id[s->n_ports_out] = port_id; 4470 s->port_out_type[s->n_ports_out] = port_type; 4471 s->port_out_params[s->n_ports_out] = p; 4472 s->n_ports_out++; 4473 4474 continue; 4475 } 4476 4477 /* Anything else. */ 4478 if (err_line) 4479 *err_line = n_lines; 4480 if (err_msg) 4481 *err_msg = "Unknown I/O statement."; 4482 goto error; 4483 } 4484 4485 return s; 4486 4487 error: 4488 pipeline_iospec_free(s); 4489 4490 return NULL; 4491 } 4492 4493 int 4494 pipeline_iospec_configure(struct rte_swx_pipeline *p, 4495 struct pipeline_iospec *s, 4496 const char **err_msg) 4497 { 4498 uint32_t i; 4499 int status = 0; 4500 4501 /* Check input arguments. */ 4502 if (!p || !s) { 4503 if (err_msg) 4504 *err_msg = "Invalid input argument"; 4505 return -EINVAL; 4506 } 4507 4508 /* Mirroring. */ 4509 status = rte_swx_pipeline_mirroring_config(p, &s->mirroring_params); 4510 if (status) { 4511 if (err_msg) 4512 *err_msg = "Pipeline mirroring configuration error."; 4513 return status; 4514 } 4515 4516 /* Input ports. */ 4517 for (i = 0; i < s->n_ports_in; i++) { 4518 status = rte_swx_pipeline_port_in_config(p, 4519 i, 4520 s->port_in_type[i], 4521 s->port_in_params[i]); 4522 if (status) { 4523 if (err_msg) 4524 *err_msg = "Pipeline input port configuration error."; 4525 return status; 4526 } 4527 } 4528 4529 /* Output ports. */ 4530 for (i = 0; i < s->n_ports_out; i++) { 4531 status = rte_swx_pipeline_port_out_config(p, 4532 i, 4533 s->port_out_type[i], 4534 s->port_out_params[i]); 4535 if (status) { 4536 if (err_msg) 4537 *err_msg = "Pipeline output port configuration error."; 4538 return status; 4539 } 4540 } 4541 4542 return 0; 4543 } 4544