1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2020 Intel Corporation 3 */ 4 #include <stdint.h> 5 #include <stdlib.h> 6 #include <stdio.h> 7 #include <string.h> 8 #include <errno.h> 9 10 #include "rte_swx_pipeline.h" 11 #include "rte_swx_ctl.h" 12 13 #define MAX_LINE_LENGTH RTE_SWX_INSTRUCTION_SIZE 14 #define MAX_TOKENS RTE_SWX_INSTRUCTION_TOKENS_MAX 15 16 #define STRUCT_BLOCK 0 17 #define ACTION_BLOCK 1 18 #define TABLE_BLOCK 2 19 #define TABLE_KEY_BLOCK 3 20 #define TABLE_ACTIONS_BLOCK 4 21 #define SELECTOR_BLOCK 5 22 #define SELECTOR_SELECTOR_BLOCK 6 23 #define APPLY_BLOCK 7 24 25 /* 26 * extobj. 27 * 28 * extobj OBJ_NAME instanceof OBJ_TYPE [ pragma OBJ_CREATE_ARGS ] 29 */ 30 struct extobj_spec { 31 char *name; 32 char *extern_type_name; 33 char *pragma; 34 }; 35 36 static void 37 extobj_spec_free(struct extobj_spec *s) 38 { 39 if (!s) 40 return; 41 42 free(s->name); 43 s->name = NULL; 44 45 free(s->extern_type_name); 46 s->extern_type_name = NULL; 47 48 free(s->pragma); 49 s->pragma = NULL; 50 } 51 52 static int 53 extobj_statement_parse(struct extobj_spec *s, 54 char **tokens, 55 uint32_t n_tokens, 56 uint32_t n_lines, 57 uint32_t *err_line, 58 const char **err_msg) 59 { 60 /* Check format. */ 61 if (((n_tokens != 4) && (n_tokens != 6)) || 62 ((n_tokens == 4) && strcmp(tokens[2], "instanceof")) || 63 ((n_tokens == 6) && (strcmp(tokens[2], "instanceof") || 64 strcmp(tokens[4], "pragma")))) { 65 if (err_line) 66 *err_line = n_lines; 67 if (err_msg) 68 *err_msg = "Invalid extobj statement."; 69 return -EINVAL; 70 } 71 72 /* spec. */ 73 s->name = strdup(tokens[1]); 74 s->extern_type_name = strdup(tokens[3]); 75 s->pragma = (n_tokens == 6) ? strdup(tokens[5]) : NULL; 76 77 if (!s->name || 78 !s->extern_type_name || 79 ((n_tokens == 6) && !s->pragma)) { 80 free(s->name); 81 free(s->extern_type_name); 82 free(s->pragma); 83 84 if (err_line) 85 *err_line = n_lines; 86 if (err_msg) 87 *err_msg = "Memory allocation failed."; 88 return -ENOMEM; 89 } 90 91 return 0; 92 } 93 94 /* 95 * struct. 96 * 97 * struct STRUCT_TYPE_NAME { 98 * bit<SIZE> FIELD_NAME 99 * ... 100 * } 101 */ 102 struct struct_spec { 103 char *name; 104 struct rte_swx_field_params *fields; 105 uint32_t n_fields; 106 }; 107 108 static void 109 struct_spec_free(struct struct_spec *s) 110 { 111 uint32_t i; 112 113 if (!s) 114 return; 115 116 free(s->name); 117 s->name = NULL; 118 119 for (i = 0; i < s->n_fields; i++) { 120 uintptr_t name = (uintptr_t)s->fields[i].name; 121 122 free((void *)name); 123 } 124 125 free(s->fields); 126 s->fields = NULL; 127 128 s->n_fields = 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; 176 uint32_t n_bits; 177 178 /* Handle end of block. */ 179 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 180 *block_mask &= ~(1 << STRUCT_BLOCK); 181 return 0; 182 } 183 184 /* Check format. */ 185 if ((n_tokens != 2) || 186 (strlen(p) < 6) || 187 (p[0] != 'b') || 188 (p[1] != 'i') || 189 (p[2] != 't') || 190 (p[3] != '<') || 191 (p[strlen(p) - 1] != '>')) { 192 if (err_line) 193 *err_line = n_lines; 194 if (err_msg) 195 *err_msg = "Invalid struct field statement."; 196 return -EINVAL; 197 } 198 199 /* Remove the "bit<" and ">". */ 200 p[strlen(p) - 1] = 0; 201 p += 4; 202 203 n_bits = strtoul(p, &p, 0); 204 if ((p[0]) || 205 !n_bits || 206 (n_bits % 8) || 207 (n_bits > 64)) { 208 if (err_line) 209 *err_line = n_lines; 210 if (err_msg) 211 *err_msg = "Invalid struct field size."; 212 return -EINVAL; 213 } 214 215 /* spec. */ 216 name = strdup(tokens[1]); 217 if (!name) { 218 if (err_line) 219 *err_line = n_lines; 220 if (err_msg) 221 *err_msg = "Memory allocation failed."; 222 return -ENOMEM; 223 } 224 225 new_fields = realloc(s->fields, 226 (s->n_fields + 1) * sizeof(struct rte_swx_field_params)); 227 if (!new_fields) { 228 free(name); 229 230 if (err_line) 231 *err_line = n_lines; 232 if (err_msg) 233 *err_msg = "Memory allocation failed."; 234 return -ENOMEM; 235 } 236 237 s->fields = new_fields; 238 s->fields[s->n_fields].name = name; 239 s->fields[s->n_fields].n_bits = n_bits; 240 s->n_fields++; 241 242 return 0; 243 } 244 245 /* 246 * header. 247 * 248 * header HEADER_NAME instanceof STRUCT_TYPE_NAME 249 */ 250 struct header_spec { 251 char *name; 252 char *struct_type_name; 253 }; 254 255 static void 256 header_spec_free(struct header_spec *s) 257 { 258 if (!s) 259 return; 260 261 free(s->name); 262 s->name = NULL; 263 264 free(s->struct_type_name); 265 s->struct_type_name = NULL; 266 } 267 268 static int 269 header_statement_parse(struct header_spec *s, 270 char **tokens, 271 uint32_t n_tokens, 272 uint32_t n_lines, 273 uint32_t *err_line, 274 const char **err_msg) 275 { 276 /* Check format. */ 277 if ((n_tokens != 4) || strcmp(tokens[2], "instanceof")) { 278 if (err_line) 279 *err_line = n_lines; 280 if (err_msg) 281 *err_msg = "Invalid header statement."; 282 return -EINVAL; 283 } 284 285 /* spec. */ 286 s->name = strdup(tokens[1]); 287 s->struct_type_name = strdup(tokens[3]); 288 289 if (!s->name || !s->struct_type_name) { 290 free(s->name); 291 free(s->struct_type_name); 292 293 if (err_line) 294 *err_line = n_lines; 295 if (err_msg) 296 *err_msg = "Memory allocation failed."; 297 return -ENOMEM; 298 } 299 300 return 0; 301 } 302 303 /* 304 * metadata. 305 * 306 * metadata instanceof STRUCT_TYPE_NAME 307 */ 308 struct metadata_spec { 309 char *struct_type_name; 310 }; 311 312 static void 313 metadata_spec_free(struct metadata_spec *s) 314 { 315 if (!s) 316 return; 317 318 free(s->struct_type_name); 319 s->struct_type_name = NULL; 320 } 321 322 static int 323 metadata_statement_parse(struct metadata_spec *s, 324 char **tokens, 325 uint32_t n_tokens, 326 uint32_t n_lines, 327 uint32_t *err_line, 328 const char **err_msg) 329 { 330 /* Check format. */ 331 if ((n_tokens != 3) || strcmp(tokens[1], "instanceof")) { 332 if (err_line) 333 *err_line = n_lines; 334 if (err_msg) 335 *err_msg = "Invalid metadata statement."; 336 return -EINVAL; 337 } 338 339 /* spec. */ 340 s->struct_type_name = strdup(tokens[2]); 341 if (!s->struct_type_name) { 342 if (err_line) 343 *err_line = n_lines; 344 if (err_msg) 345 *err_msg = "Memory allocation failed."; 346 return -ENOMEM; 347 } 348 349 return 0; 350 } 351 352 /* 353 * action. 354 * 355 * action ACTION_NAME args none | instanceof STRUCT_TYPE_NAME { 356 * INSTRUCTION 357 * ... 358 * } 359 */ 360 struct action_spec { 361 char *name; 362 char *args_struct_type_name; 363 const char **instructions; 364 uint32_t n_instructions; 365 }; 366 367 static void 368 action_spec_free(struct action_spec *s) 369 { 370 uint32_t i; 371 372 if (!s) 373 return; 374 375 free(s->name); 376 s->name = NULL; 377 378 free(s->args_struct_type_name); 379 s->args_struct_type_name = NULL; 380 381 for (i = 0; i < s->n_instructions; i++) { 382 uintptr_t instr = (uintptr_t)s->instructions[i]; 383 384 free((void *)instr); 385 } 386 387 free(s->instructions); 388 s->instructions = NULL; 389 390 s->n_instructions = 0; 391 } 392 393 static int 394 action_statement_parse(struct action_spec *s, 395 uint32_t *block_mask, 396 char **tokens, 397 uint32_t n_tokens, 398 uint32_t n_lines, 399 uint32_t *err_line, 400 const char **err_msg) 401 { 402 /* Check format. */ 403 if (((n_tokens != 5) && (n_tokens != 6)) || 404 ((n_tokens == 5) && 405 (strcmp(tokens[2], "args") || 406 strcmp(tokens[3], "none") || 407 strcmp(tokens[4], "{"))) || 408 ((n_tokens == 6) && 409 (strcmp(tokens[2], "args") || 410 strcmp(tokens[3], "instanceof") || 411 strcmp(tokens[5], "{")))) { 412 if (err_line) 413 *err_line = n_lines; 414 if (err_msg) 415 *err_msg = "Invalid action statement."; 416 return -EINVAL; 417 } 418 419 /* spec. */ 420 s->name = strdup(tokens[1]); 421 s->args_struct_type_name = (n_tokens == 6) ? strdup(tokens[4]) : NULL; 422 423 if ((!s->name) || ((n_tokens == 6) && !s->args_struct_type_name)) { 424 if (err_line) 425 *err_line = n_lines; 426 if (err_msg) 427 *err_msg = "Memory allocation failed."; 428 return -ENOMEM; 429 } 430 431 /* block_mask. */ 432 *block_mask |= 1 << ACTION_BLOCK; 433 434 return 0; 435 } 436 437 static int 438 action_block_parse(struct action_spec *s, 439 uint32_t *block_mask, 440 char **tokens, 441 uint32_t n_tokens, 442 uint32_t n_lines, 443 uint32_t *err_line, 444 const char **err_msg) 445 { 446 char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr; 447 const char **new_instructions; 448 uint32_t i; 449 450 /* Handle end of block. */ 451 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 452 *block_mask &= ~(1 << ACTION_BLOCK); 453 return 0; 454 } 455 456 /* spec. */ 457 buffer[0] = 0; 458 for (i = 0; i < n_tokens; i++) { 459 if (i) 460 strcat(buffer, " "); 461 strcat(buffer, tokens[i]); 462 } 463 464 instr = strdup(buffer); 465 if (!instr) { 466 if (err_line) 467 *err_line = n_lines; 468 if (err_msg) 469 *err_msg = "Memory allocation failed."; 470 return -ENOMEM; 471 } 472 473 new_instructions = realloc(s->instructions, 474 (s->n_instructions + 1) * sizeof(char *)); 475 if (!new_instructions) { 476 free(instr); 477 478 if (err_line) 479 *err_line = n_lines; 480 if (err_msg) 481 *err_msg = "Memory allocation failed."; 482 return -ENOMEM; 483 } 484 485 s->instructions = new_instructions; 486 s->instructions[s->n_instructions] = instr; 487 s->n_instructions++; 488 489 return 0; 490 } 491 492 /* 493 * table. 494 * 495 * table { 496 * key { 497 * MATCH_FIELD_NAME exact | wildcard | lpm 498 * ... 499 * } 500 * actions { 501 * ACTION_NAME 502 * ... 503 * } 504 * default_action ACTION_NAME args none | ARGS_BYTE_ARRAY [ const ] 505 * instanceof TABLE_TYPE_NAME 506 * pragma ARGS 507 * size SIZE 508 * } 509 */ 510 struct table_spec { 511 char *name; 512 struct rte_swx_pipeline_table_params params; 513 char *recommended_table_type_name; 514 char *args; 515 uint32_t size; 516 }; 517 518 static void 519 table_spec_free(struct table_spec *s) 520 { 521 uintptr_t default_action_name; 522 uint32_t i; 523 524 if (!s) 525 return; 526 527 free(s->name); 528 s->name = NULL; 529 530 for (i = 0; i < s->params.n_fields; i++) { 531 uintptr_t name = (uintptr_t)s->params.fields[i].name; 532 533 free((void *)name); 534 } 535 536 free(s->params.fields); 537 s->params.fields = NULL; 538 539 s->params.n_fields = 0; 540 541 for (i = 0; i < s->params.n_actions; i++) { 542 uintptr_t name = (uintptr_t)s->params.action_names[i]; 543 544 free((void *)name); 545 } 546 547 free(s->params.action_names); 548 s->params.action_names = NULL; 549 550 s->params.n_actions = 0; 551 552 default_action_name = (uintptr_t)s->params.default_action_name; 553 free((void *)default_action_name); 554 s->params.default_action_name = NULL; 555 556 free(s->params.default_action_data); 557 s->params.default_action_data = NULL; 558 559 s->params.default_action_is_const = 0; 560 561 free(s->recommended_table_type_name); 562 s->recommended_table_type_name = NULL; 563 564 free(s->args); 565 s->args = NULL; 566 567 s->size = 0; 568 } 569 570 static int 571 table_key_statement_parse(uint32_t *block_mask, 572 char **tokens, 573 uint32_t n_tokens, 574 uint32_t n_lines, 575 uint32_t *err_line, 576 const char **err_msg) 577 { 578 /* Check format. */ 579 if ((n_tokens != 2) || strcmp(tokens[1], "{")) { 580 if (err_line) 581 *err_line = n_lines; 582 if (err_msg) 583 *err_msg = "Invalid key statement."; 584 return -EINVAL; 585 } 586 587 /* block_mask. */ 588 *block_mask |= 1 << TABLE_KEY_BLOCK; 589 590 return 0; 591 } 592 593 static int 594 table_key_block_parse(struct table_spec *s, 595 uint32_t *block_mask, 596 char **tokens, 597 uint32_t n_tokens, 598 uint32_t n_lines, 599 uint32_t *err_line, 600 const char **err_msg) 601 { 602 struct rte_swx_match_field_params *new_fields; 603 enum rte_swx_table_match_type match_type = RTE_SWX_TABLE_MATCH_WILDCARD; 604 char *name; 605 606 /* Handle end of block. */ 607 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 608 *block_mask &= ~(1 << TABLE_KEY_BLOCK); 609 return 0; 610 } 611 612 /* Check input arguments. */ 613 if ((n_tokens != 2) || 614 (strcmp(tokens[1], "exact") && 615 strcmp(tokens[1], "wildcard") && 616 strcmp(tokens[1], "lpm"))) { 617 if (err_line) 618 *err_line = n_lines; 619 if (err_msg) 620 *err_msg = "Invalid match field statement."; 621 return -EINVAL; 622 } 623 624 if (!strcmp(tokens[1], "wildcard")) 625 match_type = RTE_SWX_TABLE_MATCH_WILDCARD; 626 if (!strcmp(tokens[1], "lpm")) 627 match_type = RTE_SWX_TABLE_MATCH_LPM; 628 if (!strcmp(tokens[1], "exact")) 629 match_type = RTE_SWX_TABLE_MATCH_EXACT; 630 631 name = strdup(tokens[0]); 632 if (!name) { 633 if (err_line) 634 *err_line = n_lines; 635 if (err_msg) 636 *err_msg = "Memory allocation failed."; 637 return -ENOMEM; 638 } 639 640 new_fields = realloc(s->params.fields, 641 (s->params.n_fields + 1) * sizeof(struct rte_swx_match_field_params)); 642 if (!new_fields) { 643 free(name); 644 645 if (err_line) 646 *err_line = n_lines; 647 if (err_msg) 648 *err_msg = "Memory allocation failed."; 649 return -ENOMEM; 650 } 651 652 s->params.fields = new_fields; 653 s->params.fields[s->params.n_fields].name = name; 654 s->params.fields[s->params.n_fields].match_type = match_type; 655 s->params.n_fields++; 656 657 return 0; 658 } 659 660 static int 661 table_actions_statement_parse(uint32_t *block_mask, 662 char **tokens, 663 uint32_t n_tokens, 664 uint32_t n_lines, 665 uint32_t *err_line, 666 const char **err_msg) 667 { 668 /* Check format. */ 669 if ((n_tokens != 2) || strcmp(tokens[1], "{")) { 670 if (err_line) 671 *err_line = n_lines; 672 if (err_msg) 673 *err_msg = "Invalid actions statement."; 674 return -EINVAL; 675 } 676 677 /* block_mask. */ 678 *block_mask |= 1 << TABLE_ACTIONS_BLOCK; 679 680 return 0; 681 } 682 683 static int 684 table_actions_block_parse(struct table_spec *s, 685 uint32_t *block_mask, 686 char **tokens, 687 uint32_t n_tokens, 688 uint32_t n_lines, 689 uint32_t *err_line, 690 const char **err_msg) 691 { 692 const char **new_action_names; 693 char *name; 694 695 /* Handle end of block. */ 696 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 697 *block_mask &= ~(1 << TABLE_ACTIONS_BLOCK); 698 return 0; 699 } 700 701 /* Check input arguments. */ 702 if (n_tokens != 1) { 703 if (err_line) 704 *err_line = n_lines; 705 if (err_msg) 706 *err_msg = "Invalid action name statement."; 707 return -EINVAL; 708 } 709 710 name = strdup(tokens[0]); 711 if (!name) { 712 if (err_line) 713 *err_line = n_lines; 714 if (err_msg) 715 *err_msg = "Memory allocation failed."; 716 return -ENOMEM; 717 } 718 719 new_action_names = realloc(s->params.action_names, 720 (s->params.n_actions + 1) * sizeof(char *)); 721 if (!new_action_names) { 722 free(name); 723 724 if (err_line) 725 *err_line = n_lines; 726 if (err_msg) 727 *err_msg = "Memory allocation failed."; 728 return -ENOMEM; 729 } 730 731 s->params.action_names = new_action_names; 732 s->params.action_names[s->params.n_actions] = name; 733 s->params.n_actions++; 734 735 return 0; 736 } 737 738 static int 739 table_statement_parse(struct table_spec *s, 740 uint32_t *block_mask, 741 char **tokens, 742 uint32_t n_tokens, 743 uint32_t n_lines, 744 uint32_t *err_line, 745 const char **err_msg) 746 { 747 /* Check format. */ 748 if ((n_tokens != 3) || strcmp(tokens[2], "{")) { 749 if (err_line) 750 *err_line = n_lines; 751 if (err_msg) 752 *err_msg = "Invalid table statement."; 753 return -EINVAL; 754 } 755 756 /* spec. */ 757 s->name = strdup(tokens[1]); 758 if (!s->name) { 759 if (err_line) 760 *err_line = n_lines; 761 if (err_msg) 762 *err_msg = "Memory allocation failed."; 763 return -ENOMEM; 764 } 765 766 /* block_mask. */ 767 *block_mask |= 1 << TABLE_BLOCK; 768 769 return 0; 770 } 771 772 static int 773 table_block_parse(struct table_spec *s, 774 uint32_t *block_mask, 775 char **tokens, 776 uint32_t n_tokens, 777 uint32_t n_lines, 778 uint32_t *err_line, 779 const char **err_msg) 780 { 781 if (*block_mask & (1 << TABLE_KEY_BLOCK)) 782 return table_key_block_parse(s, 783 block_mask, 784 tokens, 785 n_tokens, 786 n_lines, 787 err_line, 788 err_msg); 789 790 if (*block_mask & (1 << TABLE_ACTIONS_BLOCK)) 791 return table_actions_block_parse(s, 792 block_mask, 793 tokens, 794 n_tokens, 795 n_lines, 796 err_line, 797 err_msg); 798 799 /* Handle end of block. */ 800 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 801 *block_mask &= ~(1 << TABLE_BLOCK); 802 return 0; 803 } 804 805 if (!strcmp(tokens[0], "key")) 806 return table_key_statement_parse(block_mask, 807 tokens, 808 n_tokens, 809 n_lines, 810 err_line, 811 err_msg); 812 813 if (!strcmp(tokens[0], "actions")) 814 return table_actions_statement_parse(block_mask, 815 tokens, 816 n_tokens, 817 n_lines, 818 err_line, 819 err_msg); 820 821 if (!strcmp(tokens[0], "default_action")) { 822 if (((n_tokens != 4) && (n_tokens != 5)) || 823 strcmp(tokens[2], "args") || 824 strcmp(tokens[3], "none") || 825 ((n_tokens == 5) && strcmp(tokens[4], "const"))) { 826 if (err_line) 827 *err_line = n_lines; 828 if (err_msg) 829 *err_msg = "Invalid default_action statement."; 830 return -EINVAL; 831 } 832 833 if (s->params.default_action_name) { 834 if (err_line) 835 *err_line = n_lines; 836 if (err_msg) 837 *err_msg = "Duplicate default_action stmt."; 838 return -EINVAL; 839 } 840 841 s->params.default_action_name = strdup(tokens[1]); 842 if (!s->params.default_action_name) { 843 if (err_line) 844 *err_line = n_lines; 845 if (err_msg) 846 *err_msg = "Memory allocation failed."; 847 return -ENOMEM; 848 } 849 850 if (n_tokens == 5) 851 s->params.default_action_is_const = 1; 852 853 return 0; 854 } 855 856 if (!strcmp(tokens[0], "instanceof")) { 857 if (n_tokens != 2) { 858 if (err_line) 859 *err_line = n_lines; 860 if (err_msg) 861 *err_msg = "Invalid instanceof statement."; 862 return -EINVAL; 863 } 864 865 if (s->recommended_table_type_name) { 866 if (err_line) 867 *err_line = n_lines; 868 if (err_msg) 869 *err_msg = "Duplicate instanceof statement."; 870 return -EINVAL; 871 } 872 873 s->recommended_table_type_name = strdup(tokens[1]); 874 if (!s->recommended_table_type_name) { 875 if (err_line) 876 *err_line = n_lines; 877 if (err_msg) 878 *err_msg = "Memory allocation failed."; 879 return -ENOMEM; 880 } 881 882 return 0; 883 } 884 885 if (!strcmp(tokens[0], "pragma")) { 886 if (n_tokens != 2) { 887 if (err_line) 888 *err_line = n_lines; 889 if (err_msg) 890 *err_msg = "Invalid pragma statement."; 891 return -EINVAL; 892 } 893 894 if (s->args) { 895 if (err_line) 896 *err_line = n_lines; 897 if (err_msg) 898 *err_msg = "Duplicate pragma statement."; 899 return -EINVAL; 900 } 901 902 s->args = strdup(tokens[1]); 903 if (!s->args) { 904 if (err_line) 905 *err_line = n_lines; 906 if (err_msg) 907 *err_msg = "Memory allocation failed."; 908 return -ENOMEM; 909 } 910 911 return 0; 912 } 913 914 if (!strcmp(tokens[0], "size")) { 915 char *p = tokens[1]; 916 917 if (n_tokens != 2) { 918 if (err_line) 919 *err_line = n_lines; 920 if (err_msg) 921 *err_msg = "Invalid pragma statement."; 922 return -EINVAL; 923 } 924 925 s->size = strtoul(p, &p, 0); 926 if (p[0]) { 927 if (err_line) 928 *err_line = n_lines; 929 if (err_msg) 930 *err_msg = "Invalid size argument."; 931 return -EINVAL; 932 } 933 934 return 0; 935 } 936 937 /* Anything else. */ 938 if (err_line) 939 *err_line = n_lines; 940 if (err_msg) 941 *err_msg = "Invalid statement."; 942 return -EINVAL; 943 } 944 945 /* 946 * selector. 947 * 948 * selector SELECTOR_NAME { 949 * group_id FIELD_NAME 950 * selector { 951 * FIELD_NAME 952 * ... 953 * } 954 * member_id FIELD_NAME 955 * n_groups N_GROUPS 956 * n_members_per_group N_MEMBERS_PER_GROUP 957 * } 958 */ 959 struct selector_spec { 960 char *name; 961 struct rte_swx_pipeline_selector_params params; 962 }; 963 964 static void 965 selector_spec_free(struct selector_spec *s) 966 { 967 uintptr_t field_name; 968 uint32_t i; 969 970 if (!s) 971 return; 972 973 /* name. */ 974 free(s->name); 975 s->name = NULL; 976 977 /* params->group_id_field_name. */ 978 field_name = (uintptr_t)s->params.group_id_field_name; 979 free((void *)field_name); 980 s->params.group_id_field_name = NULL; 981 982 /* params->selector_field_names. */ 983 for (i = 0; i < s->params.n_selector_fields; i++) { 984 field_name = (uintptr_t)s->params.selector_field_names[i]; 985 986 free((void *)field_name); 987 } 988 989 free(s->params.selector_field_names); 990 s->params.selector_field_names = NULL; 991 992 s->params.n_selector_fields = 0; 993 994 /* params->member_id_field_name. */ 995 field_name = (uintptr_t)s->params.member_id_field_name; 996 free((void *)field_name); 997 s->params.member_id_field_name = NULL; 998 999 /* params->n_groups_max. */ 1000 s->params.n_groups_max = 0; 1001 1002 /* params->n_members_per_group_max. */ 1003 s->params.n_members_per_group_max = 0; 1004 } 1005 1006 static int 1007 selector_statement_parse(struct selector_spec *s, 1008 uint32_t *block_mask, 1009 char **tokens, 1010 uint32_t n_tokens, 1011 uint32_t n_lines, 1012 uint32_t *err_line, 1013 const char **err_msg) 1014 { 1015 /* Check format. */ 1016 if ((n_tokens != 3) || strcmp(tokens[2], "{")) { 1017 if (err_line) 1018 *err_line = n_lines; 1019 if (err_msg) 1020 *err_msg = "Invalid selector statement."; 1021 return -EINVAL; 1022 } 1023 1024 /* spec. */ 1025 s->name = strdup(tokens[1]); 1026 if (!s->name) { 1027 if (err_line) 1028 *err_line = n_lines; 1029 if (err_msg) 1030 *err_msg = "Memory allocation failed."; 1031 return -ENOMEM; 1032 } 1033 1034 /* block_mask. */ 1035 *block_mask |= 1 << SELECTOR_BLOCK; 1036 1037 return 0; 1038 } 1039 1040 static int 1041 selector_selector_statement_parse(uint32_t *block_mask, 1042 char **tokens, 1043 uint32_t n_tokens, 1044 uint32_t n_lines, 1045 uint32_t *err_line, 1046 const char **err_msg) 1047 { 1048 /* Check format. */ 1049 if ((n_tokens != 2) || strcmp(tokens[1], "{")) { 1050 if (err_line) 1051 *err_line = n_lines; 1052 if (err_msg) 1053 *err_msg = "Invalid selector statement."; 1054 return -EINVAL; 1055 } 1056 1057 /* block_mask. */ 1058 *block_mask |= 1 << SELECTOR_SELECTOR_BLOCK; 1059 1060 return 0; 1061 } 1062 1063 static int 1064 selector_selector_block_parse(struct selector_spec *s, 1065 uint32_t *block_mask, 1066 char **tokens, 1067 uint32_t n_tokens, 1068 uint32_t n_lines, 1069 uint32_t *err_line, 1070 const char **err_msg) 1071 { 1072 const char **new_fields; 1073 char *name; 1074 1075 /* Handle end of block. */ 1076 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 1077 *block_mask &= ~(1 << SELECTOR_SELECTOR_BLOCK); 1078 return 0; 1079 } 1080 1081 /* Check input arguments. */ 1082 if (n_tokens != 1) { 1083 if (err_line) 1084 *err_line = n_lines; 1085 if (err_msg) 1086 *err_msg = "Invalid selector field statement."; 1087 return -EINVAL; 1088 } 1089 1090 name = strdup(tokens[0]); 1091 if (!name) { 1092 if (err_line) 1093 *err_line = n_lines; 1094 if (err_msg) 1095 *err_msg = "Memory allocation failed."; 1096 return -ENOMEM; 1097 } 1098 1099 new_fields = realloc(s->params.selector_field_names, 1100 (s->params.n_selector_fields + 1) * sizeof(char *)); 1101 if (!new_fields) { 1102 free(name); 1103 1104 if (err_line) 1105 *err_line = n_lines; 1106 if (err_msg) 1107 *err_msg = "Memory allocation failed."; 1108 return -ENOMEM; 1109 } 1110 1111 s->params.selector_field_names = new_fields; 1112 s->params.selector_field_names[s->params.n_selector_fields] = name; 1113 s->params.n_selector_fields++; 1114 1115 return 0; 1116 } 1117 1118 static int 1119 selector_block_parse(struct selector_spec *s, 1120 uint32_t *block_mask, 1121 char **tokens, 1122 uint32_t n_tokens, 1123 uint32_t n_lines, 1124 uint32_t *err_line, 1125 const char **err_msg) 1126 { 1127 if (*block_mask & (1 << SELECTOR_SELECTOR_BLOCK)) 1128 return selector_selector_block_parse(s, 1129 block_mask, 1130 tokens, 1131 n_tokens, 1132 n_lines, 1133 err_line, 1134 err_msg); 1135 1136 /* Handle end of block. */ 1137 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 1138 *block_mask &= ~(1 << SELECTOR_BLOCK); 1139 return 0; 1140 } 1141 1142 if (!strcmp(tokens[0], "group_id")) { 1143 if (n_tokens != 2) { 1144 if (err_line) 1145 *err_line = n_lines; 1146 if (err_msg) 1147 *err_msg = "Invalid group_id statement."; 1148 return -EINVAL; 1149 } 1150 1151 s->params.group_id_field_name = strdup(tokens[1]); 1152 if (!s->params.group_id_field_name) { 1153 if (err_line) 1154 *err_line = n_lines; 1155 if (err_msg) 1156 *err_msg = "Memory allocation failed."; 1157 return -ENOMEM; 1158 } 1159 1160 return 0; 1161 } 1162 1163 if (!strcmp(tokens[0], "selector")) 1164 return selector_selector_statement_parse(block_mask, 1165 tokens, 1166 n_tokens, 1167 n_lines, 1168 err_line, 1169 err_msg); 1170 1171 if (!strcmp(tokens[0], "member_id")) { 1172 if (n_tokens != 2) { 1173 if (err_line) 1174 *err_line = n_lines; 1175 if (err_msg) 1176 *err_msg = "Invalid member_id statement."; 1177 return -EINVAL; 1178 } 1179 1180 s->params.member_id_field_name = strdup(tokens[1]); 1181 if (!s->params.member_id_field_name) { 1182 if (err_line) 1183 *err_line = n_lines; 1184 if (err_msg) 1185 *err_msg = "Memory allocation failed."; 1186 return -ENOMEM; 1187 } 1188 1189 return 0; 1190 } 1191 1192 if (!strcmp(tokens[0], "n_groups_max")) { 1193 char *p = tokens[1]; 1194 1195 if (n_tokens != 2) { 1196 if (err_line) 1197 *err_line = n_lines; 1198 if (err_msg) 1199 *err_msg = "Invalid n_groups statement."; 1200 return -EINVAL; 1201 } 1202 1203 s->params.n_groups_max = strtoul(p, &p, 0); 1204 if (p[0]) { 1205 if (err_line) 1206 *err_line = n_lines; 1207 if (err_msg) 1208 *err_msg = "Invalid n_groups argument."; 1209 return -EINVAL; 1210 } 1211 1212 return 0; 1213 } 1214 1215 if (!strcmp(tokens[0], "n_members_per_group_max")) { 1216 char *p = tokens[1]; 1217 1218 if (n_tokens != 2) { 1219 if (err_line) 1220 *err_line = n_lines; 1221 if (err_msg) 1222 *err_msg = "Invalid n_members_per_group statement."; 1223 return -EINVAL; 1224 } 1225 1226 s->params.n_members_per_group_max = strtoul(p, &p, 0); 1227 if (p[0]) { 1228 if (err_line) 1229 *err_line = n_lines; 1230 if (err_msg) 1231 *err_msg = "Invalid n_members_per_group argument."; 1232 return -EINVAL; 1233 } 1234 1235 return 0; 1236 } 1237 1238 /* Anything else. */ 1239 if (err_line) 1240 *err_line = n_lines; 1241 if (err_msg) 1242 *err_msg = "Invalid statement."; 1243 return -EINVAL; 1244 } 1245 1246 /* 1247 * regarray. 1248 * 1249 * regarray NAME size SIZE initval INITVAL 1250 */ 1251 struct regarray_spec { 1252 char *name; 1253 uint64_t init_val; 1254 uint32_t size; 1255 }; 1256 1257 static void 1258 regarray_spec_free(struct regarray_spec *s) 1259 { 1260 if (!s) 1261 return; 1262 1263 free(s->name); 1264 s->name = NULL; 1265 } 1266 1267 static int 1268 regarray_statement_parse(struct regarray_spec *s, 1269 char **tokens, 1270 uint32_t n_tokens, 1271 uint32_t n_lines, 1272 uint32_t *err_line, 1273 const char **err_msg) 1274 { 1275 char *p; 1276 1277 /* Check format. */ 1278 if ((n_tokens != 6) || 1279 strcmp(tokens[2], "size") || 1280 strcmp(tokens[4], "initval")) { 1281 if (err_line) 1282 *err_line = n_lines; 1283 if (err_msg) 1284 *err_msg = "Invalid regarray statement."; 1285 return -EINVAL; 1286 } 1287 1288 /* spec. */ 1289 s->name = strdup(tokens[1]); 1290 if (!s->name) { 1291 if (err_line) 1292 *err_line = n_lines; 1293 if (err_msg) 1294 *err_msg = "Memory allocation failed."; 1295 return -ENOMEM; 1296 } 1297 1298 p = tokens[3]; 1299 s->size = strtoul(p, &p, 0); 1300 if (p[0] || !s->size) { 1301 if (err_line) 1302 *err_line = n_lines; 1303 if (err_msg) 1304 *err_msg = "Invalid size argument."; 1305 return -EINVAL; 1306 } 1307 1308 p = tokens[5]; 1309 s->init_val = strtoull(p, &p, 0); 1310 if (p[0]) { 1311 if (err_line) 1312 *err_line = n_lines; 1313 if (err_msg) 1314 *err_msg = "Invalid initval argument."; 1315 return -EINVAL; 1316 } 1317 1318 return 0; 1319 } 1320 1321 /* 1322 * metarray. 1323 * 1324 * metarray NAME size SIZE 1325 */ 1326 struct metarray_spec { 1327 char *name; 1328 uint32_t size; 1329 }; 1330 1331 static void 1332 metarray_spec_free(struct metarray_spec *s) 1333 { 1334 if (!s) 1335 return; 1336 1337 free(s->name); 1338 s->name = NULL; 1339 } 1340 1341 static int 1342 metarray_statement_parse(struct metarray_spec *s, 1343 char **tokens, 1344 uint32_t n_tokens, 1345 uint32_t n_lines, 1346 uint32_t *err_line, 1347 const char **err_msg) 1348 { 1349 char *p; 1350 1351 /* Check format. */ 1352 if ((n_tokens != 4) || strcmp(tokens[2], "size")) { 1353 if (err_line) 1354 *err_line = n_lines; 1355 if (err_msg) 1356 *err_msg = "Invalid metarray statement."; 1357 return -EINVAL; 1358 } 1359 1360 /* spec. */ 1361 s->name = strdup(tokens[1]); 1362 if (!s->name) { 1363 if (err_line) 1364 *err_line = n_lines; 1365 if (err_msg) 1366 *err_msg = "Memory allocation failed."; 1367 return -ENOMEM; 1368 } 1369 1370 p = tokens[3]; 1371 s->size = strtoul(p, &p, 0); 1372 if (p[0] || !s->size) { 1373 if (err_line) 1374 *err_line = n_lines; 1375 if (err_msg) 1376 *err_msg = "Invalid size argument."; 1377 return -EINVAL; 1378 } 1379 1380 return 0; 1381 } 1382 1383 /* 1384 * apply. 1385 * 1386 * apply { 1387 * INSTRUCTION 1388 * ... 1389 * } 1390 */ 1391 struct apply_spec { 1392 const char **instructions; 1393 uint32_t n_instructions; 1394 }; 1395 1396 static void 1397 apply_spec_free(struct apply_spec *s) 1398 { 1399 uint32_t i; 1400 1401 if (!s) 1402 return; 1403 1404 for (i = 0; i < s->n_instructions; i++) { 1405 uintptr_t instr = (uintptr_t)s->instructions[i]; 1406 1407 free((void *)instr); 1408 } 1409 1410 free(s->instructions); 1411 s->instructions = NULL; 1412 1413 s->n_instructions = 0; 1414 } 1415 1416 static int 1417 apply_statement_parse(uint32_t *block_mask, 1418 char **tokens, 1419 uint32_t n_tokens, 1420 uint32_t n_lines, 1421 uint32_t *err_line, 1422 const char **err_msg) 1423 { 1424 /* Check format. */ 1425 if ((n_tokens != 2) || strcmp(tokens[1], "{")) { 1426 if (err_line) 1427 *err_line = n_lines; 1428 if (err_msg) 1429 *err_msg = "Invalid apply statement."; 1430 return -EINVAL; 1431 } 1432 1433 /* block_mask. */ 1434 *block_mask |= 1 << APPLY_BLOCK; 1435 1436 return 0; 1437 } 1438 1439 static int 1440 apply_block_parse(struct apply_spec *s, 1441 uint32_t *block_mask, 1442 char **tokens, 1443 uint32_t n_tokens, 1444 uint32_t n_lines, 1445 uint32_t *err_line, 1446 const char **err_msg) 1447 { 1448 char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr; 1449 const char **new_instructions; 1450 uint32_t i; 1451 1452 /* Handle end of block. */ 1453 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 1454 *block_mask &= ~(1 << APPLY_BLOCK); 1455 return 0; 1456 } 1457 1458 /* spec. */ 1459 buffer[0] = 0; 1460 for (i = 0; i < n_tokens; i++) { 1461 if (i) 1462 strcat(buffer, " "); 1463 strcat(buffer, tokens[i]); 1464 } 1465 1466 instr = strdup(buffer); 1467 if (!instr) { 1468 if (err_line) 1469 *err_line = n_lines; 1470 if (err_msg) 1471 *err_msg = "Memory allocation failed."; 1472 return -ENOMEM; 1473 } 1474 1475 new_instructions = realloc(s->instructions, 1476 (s->n_instructions + 1) * sizeof(char *)); 1477 if (!new_instructions) { 1478 free(instr); 1479 1480 if (err_line) 1481 *err_line = n_lines; 1482 if (err_msg) 1483 *err_msg = "Memory allocation failed."; 1484 return -ENOMEM; 1485 } 1486 1487 s->instructions = new_instructions; 1488 s->instructions[s->n_instructions] = instr; 1489 s->n_instructions++; 1490 1491 return 0; 1492 } 1493 1494 /* 1495 * Pipeline. 1496 */ 1497 int 1498 rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p, 1499 FILE *spec, 1500 uint32_t *err_line, 1501 const char **err_msg) 1502 { 1503 struct extobj_spec extobj_spec = {0}; 1504 struct struct_spec struct_spec = {0}; 1505 struct header_spec header_spec = {0}; 1506 struct metadata_spec metadata_spec = {0}; 1507 struct action_spec action_spec = {0}; 1508 struct table_spec table_spec = {0}; 1509 struct selector_spec selector_spec = {0}; 1510 struct regarray_spec regarray_spec = {0}; 1511 struct metarray_spec metarray_spec = {0}; 1512 struct apply_spec apply_spec = {0}; 1513 uint32_t n_lines; 1514 uint32_t block_mask = 0; 1515 int status; 1516 1517 /* Check the input arguments. */ 1518 if (!p) { 1519 if (err_line) 1520 *err_line = 0; 1521 if (err_msg) 1522 *err_msg = "Null pipeline arument."; 1523 status = -EINVAL; 1524 goto error; 1525 } 1526 1527 if (!spec) { 1528 if (err_line) 1529 *err_line = 0; 1530 if (err_msg) 1531 *err_msg = "Null specification file argument."; 1532 status = -EINVAL; 1533 goto error; 1534 } 1535 1536 for (n_lines = 1; ; n_lines++) { 1537 char line[MAX_LINE_LENGTH]; 1538 char *tokens[MAX_TOKENS], *ptr = line; 1539 uint32_t n_tokens = 0; 1540 1541 /* Read next line. */ 1542 if (!fgets(line, sizeof(line), spec)) 1543 break; 1544 1545 /* Parse the line into tokens. */ 1546 for ( ; ; ) { 1547 char *token; 1548 1549 /* Get token. */ 1550 token = strtok_r(ptr, " \f\n\r\t\v", &ptr); 1551 if (!token) 1552 break; 1553 1554 /* Handle comments. */ 1555 if ((token[0] == '#') || 1556 (token[0] == ';') || 1557 ((token[0] == '/') && (token[1] == '/'))) { 1558 break; 1559 } 1560 1561 /* Handle excessively long lines. */ 1562 if (n_tokens >= MAX_TOKENS) { 1563 if (err_line) 1564 *err_line = n_lines; 1565 if (err_msg) 1566 *err_msg = "Too many tokens."; 1567 status = -EINVAL; 1568 goto error; 1569 } 1570 1571 /* Handle excessively long tokens. */ 1572 if (strnlen(token, RTE_SWX_NAME_SIZE) >= 1573 RTE_SWX_NAME_SIZE) { 1574 if (err_line) 1575 *err_line = n_lines; 1576 if (err_msg) 1577 *err_msg = "Token too big."; 1578 status = -EINVAL; 1579 goto error; 1580 } 1581 1582 /* Save token. */ 1583 tokens[n_tokens] = token; 1584 n_tokens++; 1585 } 1586 1587 /* Handle empty lines. */ 1588 if (!n_tokens) 1589 continue; 1590 1591 /* struct block. */ 1592 if (block_mask & (1 << STRUCT_BLOCK)) { 1593 status = struct_block_parse(&struct_spec, 1594 &block_mask, 1595 tokens, 1596 n_tokens, 1597 n_lines, 1598 err_line, 1599 err_msg); 1600 if (status) 1601 goto error; 1602 1603 if (block_mask & (1 << STRUCT_BLOCK)) 1604 continue; 1605 1606 /* End of block. */ 1607 status = rte_swx_pipeline_struct_type_register(p, 1608 struct_spec.name, 1609 struct_spec.fields, 1610 struct_spec.n_fields); 1611 if (status) { 1612 if (err_line) 1613 *err_line = n_lines; 1614 if (err_msg) 1615 *err_msg = "Struct registration error."; 1616 goto error; 1617 } 1618 1619 struct_spec_free(&struct_spec); 1620 1621 continue; 1622 } 1623 1624 /* action block. */ 1625 if (block_mask & (1 << ACTION_BLOCK)) { 1626 status = action_block_parse(&action_spec, 1627 &block_mask, 1628 tokens, 1629 n_tokens, 1630 n_lines, 1631 err_line, 1632 err_msg); 1633 if (status) 1634 goto error; 1635 1636 if (block_mask & (1 << ACTION_BLOCK)) 1637 continue; 1638 1639 /* End of block. */ 1640 status = rte_swx_pipeline_action_config(p, 1641 action_spec.name, 1642 action_spec.args_struct_type_name, 1643 action_spec.instructions, 1644 action_spec.n_instructions); 1645 if (status) { 1646 if (err_line) 1647 *err_line = n_lines; 1648 if (err_msg) 1649 *err_msg = "Action config error."; 1650 goto error; 1651 } 1652 1653 action_spec_free(&action_spec); 1654 1655 continue; 1656 } 1657 1658 /* table block. */ 1659 if (block_mask & (1 << TABLE_BLOCK)) { 1660 status = table_block_parse(&table_spec, 1661 &block_mask, 1662 tokens, 1663 n_tokens, 1664 n_lines, 1665 err_line, 1666 err_msg); 1667 if (status) 1668 goto error; 1669 1670 if (block_mask & (1 << TABLE_BLOCK)) 1671 continue; 1672 1673 /* End of block. */ 1674 status = rte_swx_pipeline_table_config(p, 1675 table_spec.name, 1676 &table_spec.params, 1677 table_spec.recommended_table_type_name, 1678 table_spec.args, 1679 table_spec.size); 1680 if (status) { 1681 if (err_line) 1682 *err_line = n_lines; 1683 if (err_msg) 1684 *err_msg = "Table configuration error."; 1685 goto error; 1686 } 1687 1688 table_spec_free(&table_spec); 1689 1690 continue; 1691 } 1692 1693 /* selector block. */ 1694 if (block_mask & (1 << SELECTOR_BLOCK)) { 1695 status = selector_block_parse(&selector_spec, 1696 &block_mask, 1697 tokens, 1698 n_tokens, 1699 n_lines, 1700 err_line, 1701 err_msg); 1702 if (status) 1703 goto error; 1704 1705 if (block_mask & (1 << SELECTOR_BLOCK)) 1706 continue; 1707 1708 /* End of block. */ 1709 status = rte_swx_pipeline_selector_config(p, 1710 selector_spec.name, 1711 &selector_spec.params); 1712 if (status) { 1713 if (err_line) 1714 *err_line = n_lines; 1715 if (err_msg) 1716 *err_msg = "Selector configuration error."; 1717 goto error; 1718 } 1719 1720 selector_spec_free(&selector_spec); 1721 1722 continue; 1723 } 1724 1725 /* apply block. */ 1726 if (block_mask & (1 << APPLY_BLOCK)) { 1727 status = apply_block_parse(&apply_spec, 1728 &block_mask, 1729 tokens, 1730 n_tokens, 1731 n_lines, 1732 err_line, 1733 err_msg); 1734 if (status) 1735 goto error; 1736 1737 if (block_mask & (1 << APPLY_BLOCK)) 1738 continue; 1739 1740 /* End of block. */ 1741 status = rte_swx_pipeline_instructions_config(p, 1742 apply_spec.instructions, 1743 apply_spec.n_instructions); 1744 if (status) { 1745 if (err_line) 1746 *err_line = n_lines; 1747 if (err_msg) 1748 *err_msg = "Pipeline instructions err."; 1749 goto error; 1750 } 1751 1752 apply_spec_free(&apply_spec); 1753 1754 continue; 1755 } 1756 1757 /* extobj. */ 1758 if (!strcmp(tokens[0], "extobj")) { 1759 status = extobj_statement_parse(&extobj_spec, 1760 tokens, 1761 n_tokens, 1762 n_lines, 1763 err_line, 1764 err_msg); 1765 if (status) 1766 goto error; 1767 1768 status = rte_swx_pipeline_extern_object_config(p, 1769 extobj_spec.name, 1770 extobj_spec.extern_type_name, 1771 extobj_spec.pragma); 1772 if (status) { 1773 if (err_line) 1774 *err_line = n_lines; 1775 if (err_msg) 1776 *err_msg = "Extern object config err."; 1777 goto error; 1778 } 1779 1780 extobj_spec_free(&extobj_spec); 1781 1782 continue; 1783 } 1784 1785 /* struct. */ 1786 if (!strcmp(tokens[0], "struct")) { 1787 status = struct_statement_parse(&struct_spec, 1788 &block_mask, 1789 tokens, 1790 n_tokens, 1791 n_lines, 1792 err_line, 1793 err_msg); 1794 if (status) 1795 goto error; 1796 1797 continue; 1798 } 1799 1800 /* header. */ 1801 if (!strcmp(tokens[0], "header")) { 1802 status = header_statement_parse(&header_spec, 1803 tokens, 1804 n_tokens, 1805 n_lines, 1806 err_line, 1807 err_msg); 1808 if (status) 1809 goto error; 1810 1811 status = rte_swx_pipeline_packet_header_register(p, 1812 header_spec.name, 1813 header_spec.struct_type_name); 1814 if (status) { 1815 if (err_line) 1816 *err_line = n_lines; 1817 if (err_msg) 1818 *err_msg = "Header registration error."; 1819 goto error; 1820 } 1821 1822 header_spec_free(&header_spec); 1823 1824 continue; 1825 } 1826 1827 /* metadata. */ 1828 if (!strcmp(tokens[0], "metadata")) { 1829 status = metadata_statement_parse(&metadata_spec, 1830 tokens, 1831 n_tokens, 1832 n_lines, 1833 err_line, 1834 err_msg); 1835 if (status) 1836 goto error; 1837 1838 status = rte_swx_pipeline_packet_metadata_register(p, 1839 metadata_spec.struct_type_name); 1840 if (status) { 1841 if (err_line) 1842 *err_line = n_lines; 1843 if (err_msg) 1844 *err_msg = "Meta-data reg err."; 1845 goto error; 1846 } 1847 1848 metadata_spec_free(&metadata_spec); 1849 1850 continue; 1851 } 1852 1853 /* action. */ 1854 if (!strcmp(tokens[0], "action")) { 1855 status = action_statement_parse(&action_spec, 1856 &block_mask, 1857 tokens, 1858 n_tokens, 1859 n_lines, 1860 err_line, 1861 err_msg); 1862 if (status) 1863 goto error; 1864 1865 continue; 1866 } 1867 1868 /* table. */ 1869 if (!strcmp(tokens[0], "table")) { 1870 status = table_statement_parse(&table_spec, 1871 &block_mask, 1872 tokens, 1873 n_tokens, 1874 n_lines, 1875 err_line, 1876 err_msg); 1877 if (status) 1878 goto error; 1879 1880 continue; 1881 } 1882 1883 /* selector. */ 1884 if (!strcmp(tokens[0], "selector")) { 1885 status = selector_statement_parse(&selector_spec, 1886 &block_mask, 1887 tokens, 1888 n_tokens, 1889 n_lines, 1890 err_line, 1891 err_msg); 1892 if (status) 1893 goto error; 1894 1895 continue; 1896 } 1897 1898 /* regarray. */ 1899 if (!strcmp(tokens[0], "regarray")) { 1900 status = regarray_statement_parse(®array_spec, 1901 tokens, 1902 n_tokens, 1903 n_lines, 1904 err_line, 1905 err_msg); 1906 if (status) 1907 goto error; 1908 1909 status = rte_swx_pipeline_regarray_config(p, 1910 regarray_spec.name, 1911 regarray_spec.size, 1912 regarray_spec.init_val); 1913 if (status) { 1914 if (err_line) 1915 *err_line = n_lines; 1916 if (err_msg) 1917 *err_msg = "Register array configuration error."; 1918 goto error; 1919 } 1920 1921 regarray_spec_free(®array_spec); 1922 1923 continue; 1924 } 1925 1926 /* metarray. */ 1927 if (!strcmp(tokens[0], "metarray")) { 1928 status = metarray_statement_parse(&metarray_spec, 1929 tokens, 1930 n_tokens, 1931 n_lines, 1932 err_line, 1933 err_msg); 1934 if (status) 1935 goto error; 1936 1937 status = rte_swx_pipeline_metarray_config(p, 1938 metarray_spec.name, 1939 metarray_spec.size); 1940 if (status) { 1941 if (err_line) 1942 *err_line = n_lines; 1943 if (err_msg) 1944 *err_msg = "Meter array configuration error."; 1945 goto error; 1946 } 1947 1948 metarray_spec_free(&metarray_spec); 1949 1950 continue; 1951 } 1952 1953 /* apply. */ 1954 if (!strcmp(tokens[0], "apply")) { 1955 status = apply_statement_parse(&block_mask, 1956 tokens, 1957 n_tokens, 1958 n_lines, 1959 err_line, 1960 err_msg); 1961 if (status) 1962 goto error; 1963 1964 continue; 1965 } 1966 1967 /* Anything else. */ 1968 if (err_line) 1969 *err_line = n_lines; 1970 if (err_msg) 1971 *err_msg = "Unknown statement."; 1972 status = -EINVAL; 1973 goto error; 1974 } 1975 1976 /* Handle unfinished block. */ 1977 if (block_mask) { 1978 if (err_line) 1979 *err_line = n_lines; 1980 if (err_msg) 1981 *err_msg = "Missing }."; 1982 status = -EINVAL; 1983 goto error; 1984 } 1985 1986 /* Pipeline build. */ 1987 status = rte_swx_pipeline_build(p); 1988 if (status) { 1989 if (err_line) 1990 *err_line = n_lines; 1991 if (err_msg) 1992 *err_msg = "Pipeline build error."; 1993 goto error; 1994 } 1995 1996 return 0; 1997 1998 error: 1999 extobj_spec_free(&extobj_spec); 2000 struct_spec_free(&struct_spec); 2001 header_spec_free(&header_spec); 2002 metadata_spec_free(&metadata_spec); 2003 action_spec_free(&action_spec); 2004 table_spec_free(&table_spec); 2005 selector_spec_free(&selector_spec); 2006 regarray_spec_free(®array_spec); 2007 metarray_spec_free(&metarray_spec); 2008 apply_spec_free(&apply_spec); 2009 return status; 2010 } 2011