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_common.h> 11 12 #include "rte_swx_pipeline.h" 13 14 #ifndef MAX_LINE_LENGTH 15 #define MAX_LINE_LENGTH 2048 16 #endif 17 18 #ifndef MAX_TOKENS 19 #define MAX_TOKENS 256 20 #endif 21 22 #define STRUCT_BLOCK 0 23 #define ACTION_BLOCK 1 24 #define TABLE_BLOCK 2 25 #define TABLE_KEY_BLOCK 3 26 #define TABLE_ACTIONS_BLOCK 4 27 #define SELECTOR_BLOCK 5 28 #define SELECTOR_SELECTOR_BLOCK 6 29 #define LEARNER_BLOCK 7 30 #define LEARNER_KEY_BLOCK 8 31 #define LEARNER_ACTIONS_BLOCK 9 32 #define LEARNER_TIMEOUT_BLOCK 10 33 #define APPLY_BLOCK 11 34 35 /* 36 * extobj. 37 * 38 * extobj OBJ_NAME instanceof OBJ_TYPE [ pragma OBJ_CREATE_ARGS ] 39 */ 40 struct extobj_spec { 41 char *name; 42 char *extern_type_name; 43 char *pragma; 44 }; 45 46 static void 47 extobj_spec_free(struct extobj_spec *s) 48 { 49 if (!s) 50 return; 51 52 free(s->name); 53 s->name = NULL; 54 55 free(s->extern_type_name); 56 s->extern_type_name = NULL; 57 58 free(s->pragma); 59 s->pragma = NULL; 60 } 61 62 static int 63 extobj_statement_parse(struct extobj_spec *s, 64 char **tokens, 65 uint32_t n_tokens, 66 uint32_t n_lines, 67 uint32_t *err_line, 68 const char **err_msg) 69 { 70 /* Check format. */ 71 if (((n_tokens != 4) && (n_tokens != 6)) || 72 ((n_tokens == 4) && strcmp(tokens[2], "instanceof")) || 73 ((n_tokens == 6) && (strcmp(tokens[2], "instanceof") || 74 strcmp(tokens[4], "pragma")))) { 75 if (err_line) 76 *err_line = n_lines; 77 if (err_msg) 78 *err_msg = "Invalid extobj statement."; 79 return -EINVAL; 80 } 81 82 /* spec. */ 83 s->name = strdup(tokens[1]); 84 s->extern_type_name = strdup(tokens[3]); 85 s->pragma = (n_tokens == 6) ? strdup(tokens[5]) : NULL; 86 87 if (!s->name || 88 !s->extern_type_name || 89 ((n_tokens == 6) && !s->pragma)) { 90 free(s->name); 91 free(s->extern_type_name); 92 free(s->pragma); 93 94 if (err_line) 95 *err_line = n_lines; 96 if (err_msg) 97 *err_msg = "Memory allocation failed."; 98 return -ENOMEM; 99 } 100 101 return 0; 102 } 103 104 /* 105 * struct. 106 * 107 * struct STRUCT_TYPE_NAME { 108 * bit<SIZE> | varbit<SIZE> FIELD_NAME 109 * ... 110 * } 111 */ 112 struct struct_spec { 113 char *name; 114 struct rte_swx_field_params *fields; 115 uint32_t n_fields; 116 int varbit; 117 }; 118 119 static void 120 struct_spec_free(struct struct_spec *s) 121 { 122 uint32_t i; 123 124 if (!s) 125 return; 126 127 free(s->name); 128 s->name = NULL; 129 130 for (i = 0; i < s->n_fields; i++) { 131 uintptr_t name = (uintptr_t)s->fields[i].name; 132 133 free((void *)name); 134 } 135 136 free(s->fields); 137 s->fields = NULL; 138 139 s->n_fields = 0; 140 141 s->varbit = 0; 142 } 143 144 static int 145 struct_statement_parse(struct struct_spec *s, 146 uint32_t *block_mask, 147 char **tokens, 148 uint32_t n_tokens, 149 uint32_t n_lines, 150 uint32_t *err_line, 151 const char **err_msg) 152 { 153 /* Check format. */ 154 if ((n_tokens != 3) || strcmp(tokens[2], "{")) { 155 if (err_line) 156 *err_line = n_lines; 157 if (err_msg) 158 *err_msg = "Invalid struct statement."; 159 return -EINVAL; 160 } 161 162 /* spec. */ 163 s->name = strdup(tokens[1]); 164 if (!s->name) { 165 if (err_line) 166 *err_line = n_lines; 167 if (err_msg) 168 *err_msg = "Memory allocation failed."; 169 return -ENOMEM; 170 } 171 172 /* block_mask. */ 173 *block_mask |= 1 << STRUCT_BLOCK; 174 175 return 0; 176 } 177 178 static int 179 struct_block_parse(struct struct_spec *s, 180 uint32_t *block_mask, 181 char **tokens, 182 uint32_t n_tokens, 183 uint32_t n_lines, 184 uint32_t *err_line, 185 const char **err_msg) 186 { 187 struct rte_swx_field_params *new_fields; 188 char *p = tokens[0], *name = NULL; 189 uint32_t n_bits; 190 int varbit = 0, error = 0, error_size_invalid = 0, error_varbit_not_last = 0; 191 192 /* Handle end of block. */ 193 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 194 *block_mask &= ~(1 << STRUCT_BLOCK); 195 return 0; 196 } 197 198 /* Check format. */ 199 if (n_tokens != 2) { 200 error = -EINVAL; 201 goto error; 202 } 203 204 if (s->varbit) { 205 error = -EINVAL; 206 error_varbit_not_last = 1; 207 goto error; 208 } 209 210 if (!strncmp(p, "bit<", strlen("bit<"))) { 211 size_t len = strlen(p); 212 213 if ((len < strlen("bit< >")) || (p[len - 1] != '>')) { 214 error = -EINVAL; 215 goto error; 216 } 217 218 /* Remove the "bit<" and ">". */ 219 p[strlen(p) - 1] = 0; 220 p += strlen("bit<"); 221 } else if (!strncmp(p, "varbit<", strlen("varbit<"))) { 222 size_t len = strlen(p); 223 224 if ((len < strlen("varbit< >")) || (p[len - 1] != '>')) { 225 error = -EINVAL; 226 goto error; 227 } 228 229 /* Remove the "varbit<" and ">". */ 230 p[strlen(p) - 1] = 0; 231 p += strlen("varbit<"); 232 233 /* Set the varbit flag. */ 234 varbit = 1; 235 } else { 236 error = -EINVAL; 237 goto error; 238 } 239 240 n_bits = strtoul(p, &p, 0); 241 if ((p[0]) || 242 !n_bits || 243 (n_bits % 8) || 244 ((n_bits > 64) && !varbit)) { 245 error = -EINVAL; 246 error_size_invalid = 1; 247 goto error; 248 } 249 250 /* spec. */ 251 name = strdup(tokens[1]); 252 if (!name) { 253 error = -ENOMEM; 254 goto error; 255 } 256 257 new_fields = realloc(s->fields, (s->n_fields + 1) * sizeof(struct rte_swx_field_params)); 258 if (!new_fields) { 259 error = -ENOMEM; 260 goto error; 261 } 262 263 s->fields = new_fields; 264 s->fields[s->n_fields].name = name; 265 s->fields[s->n_fields].n_bits = n_bits; 266 s->n_fields++; 267 s->varbit = varbit; 268 269 return 0; 270 271 error: 272 free(name); 273 274 if (err_line) 275 *err_line = n_lines; 276 277 if (err_msg) { 278 *err_msg = "Invalid struct field statement."; 279 280 if ((error == -EINVAL) && error_varbit_not_last) 281 *err_msg = "Varbit field is not the last struct field."; 282 283 if ((error == -EINVAL) && error_size_invalid) 284 *err_msg = "Invalid struct field size."; 285 286 if (error == -ENOMEM) 287 *err_msg = "Memory allocation failed."; 288 } 289 290 return error; 291 } 292 293 /* 294 * header. 295 * 296 * header HEADER_NAME instanceof STRUCT_TYPE_NAME 297 */ 298 struct header_spec { 299 char *name; 300 char *struct_type_name; 301 }; 302 303 static void 304 header_spec_free(struct header_spec *s) 305 { 306 if (!s) 307 return; 308 309 free(s->name); 310 s->name = NULL; 311 312 free(s->struct_type_name); 313 s->struct_type_name = NULL; 314 } 315 316 static int 317 header_statement_parse(struct header_spec *s, 318 char **tokens, 319 uint32_t n_tokens, 320 uint32_t n_lines, 321 uint32_t *err_line, 322 const char **err_msg) 323 { 324 /* Check format. */ 325 if ((n_tokens != 4) || strcmp(tokens[2], "instanceof")) { 326 if (err_line) 327 *err_line = n_lines; 328 if (err_msg) 329 *err_msg = "Invalid header statement."; 330 return -EINVAL; 331 } 332 333 /* spec. */ 334 s->name = strdup(tokens[1]); 335 s->struct_type_name = strdup(tokens[3]); 336 337 if (!s->name || !s->struct_type_name) { 338 free(s->name); 339 free(s->struct_type_name); 340 341 if (err_line) 342 *err_line = n_lines; 343 if (err_msg) 344 *err_msg = "Memory allocation failed."; 345 return -ENOMEM; 346 } 347 348 return 0; 349 } 350 351 /* 352 * metadata. 353 * 354 * metadata instanceof STRUCT_TYPE_NAME 355 */ 356 struct metadata_spec { 357 char *struct_type_name; 358 }; 359 360 static void 361 metadata_spec_free(struct metadata_spec *s) 362 { 363 if (!s) 364 return; 365 366 free(s->struct_type_name); 367 s->struct_type_name = NULL; 368 } 369 370 static int 371 metadata_statement_parse(struct metadata_spec *s, 372 char **tokens, 373 uint32_t n_tokens, 374 uint32_t n_lines, 375 uint32_t *err_line, 376 const char **err_msg) 377 { 378 /* Check format. */ 379 if ((n_tokens != 3) || strcmp(tokens[1], "instanceof")) { 380 if (err_line) 381 *err_line = n_lines; 382 if (err_msg) 383 *err_msg = "Invalid metadata statement."; 384 return -EINVAL; 385 } 386 387 /* spec. */ 388 s->struct_type_name = strdup(tokens[2]); 389 if (!s->struct_type_name) { 390 if (err_line) 391 *err_line = n_lines; 392 if (err_msg) 393 *err_msg = "Memory allocation failed."; 394 return -ENOMEM; 395 } 396 397 return 0; 398 } 399 400 /* 401 * action. 402 * 403 * action ACTION_NAME args none | instanceof STRUCT_TYPE_NAME { 404 * INSTRUCTION 405 * ... 406 * } 407 */ 408 struct action_spec { 409 char *name; 410 char *args_struct_type_name; 411 const char **instructions; 412 uint32_t n_instructions; 413 }; 414 415 static void 416 action_spec_free(struct action_spec *s) 417 { 418 uint32_t i; 419 420 if (!s) 421 return; 422 423 free(s->name); 424 s->name = NULL; 425 426 free(s->args_struct_type_name); 427 s->args_struct_type_name = NULL; 428 429 for (i = 0; i < s->n_instructions; i++) { 430 uintptr_t instr = (uintptr_t)s->instructions[i]; 431 432 free((void *)instr); 433 } 434 435 free(s->instructions); 436 s->instructions = NULL; 437 438 s->n_instructions = 0; 439 } 440 441 static int 442 action_statement_parse(struct action_spec *s, 443 uint32_t *block_mask, 444 char **tokens, 445 uint32_t n_tokens, 446 uint32_t n_lines, 447 uint32_t *err_line, 448 const char **err_msg) 449 { 450 /* Check format. */ 451 if (((n_tokens != 5) && (n_tokens != 6)) || 452 ((n_tokens == 5) && 453 (strcmp(tokens[2], "args") || 454 strcmp(tokens[3], "none") || 455 strcmp(tokens[4], "{"))) || 456 ((n_tokens == 6) && 457 (strcmp(tokens[2], "args") || 458 strcmp(tokens[3], "instanceof") || 459 strcmp(tokens[5], "{")))) { 460 if (err_line) 461 *err_line = n_lines; 462 if (err_msg) 463 *err_msg = "Invalid action statement."; 464 return -EINVAL; 465 } 466 467 /* spec. */ 468 s->name = strdup(tokens[1]); 469 s->args_struct_type_name = (n_tokens == 6) ? strdup(tokens[4]) : NULL; 470 471 if ((!s->name) || ((n_tokens == 6) && !s->args_struct_type_name)) { 472 if (err_line) 473 *err_line = n_lines; 474 if (err_msg) 475 *err_msg = "Memory allocation failed."; 476 return -ENOMEM; 477 } 478 479 /* block_mask. */ 480 *block_mask |= 1 << ACTION_BLOCK; 481 482 return 0; 483 } 484 485 static int 486 action_block_parse(struct action_spec *s, 487 uint32_t *block_mask, 488 char **tokens, 489 uint32_t n_tokens, 490 uint32_t n_lines, 491 uint32_t *err_line, 492 const char **err_msg) 493 { 494 char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr; 495 const char **new_instructions; 496 uint32_t i; 497 498 /* Handle end of block. */ 499 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 500 *block_mask &= ~(1 << ACTION_BLOCK); 501 return 0; 502 } 503 504 /* spec. */ 505 buffer[0] = 0; 506 for (i = 0; i < n_tokens; i++) { 507 if (i) 508 strcat(buffer, " "); 509 strcat(buffer, tokens[i]); 510 } 511 512 instr = strdup(buffer); 513 if (!instr) { 514 if (err_line) 515 *err_line = n_lines; 516 if (err_msg) 517 *err_msg = "Memory allocation failed."; 518 return -ENOMEM; 519 } 520 521 new_instructions = realloc(s->instructions, 522 (s->n_instructions + 1) * sizeof(char *)); 523 if (!new_instructions) { 524 free(instr); 525 526 if (err_line) 527 *err_line = n_lines; 528 if (err_msg) 529 *err_msg = "Memory allocation failed."; 530 return -ENOMEM; 531 } 532 533 s->instructions = new_instructions; 534 s->instructions[s->n_instructions] = instr; 535 s->n_instructions++; 536 537 return 0; 538 } 539 540 /* 541 * table. 542 * 543 * table TABLE_NAME { 544 * key { 545 * MATCH_FIELD_NAME exact | wildcard | lpm 546 * ... 547 * } 548 * actions { 549 * ACTION_NAME [ @tableonly | @defaultonly ] 550 * ... 551 * } 552 * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ] 553 * instanceof TABLE_TYPE_NAME 554 * pragma ARGS 555 * size SIZE 556 * } 557 */ 558 struct table_spec { 559 char *name; 560 struct rte_swx_pipeline_table_params params; 561 char *recommended_table_type_name; 562 char *args; 563 uint32_t size; 564 }; 565 566 static void 567 table_spec_free(struct table_spec *s) 568 { 569 uintptr_t default_action_name, default_action_args; 570 uint32_t i; 571 572 if (!s) 573 return; 574 575 free(s->name); 576 s->name = NULL; 577 578 for (i = 0; i < s->params.n_fields; i++) { 579 uintptr_t name = (uintptr_t)s->params.fields[i].name; 580 581 free((void *)name); 582 } 583 584 free(s->params.fields); 585 s->params.fields = NULL; 586 587 s->params.n_fields = 0; 588 589 for (i = 0; i < s->params.n_actions; i++) { 590 uintptr_t name = (uintptr_t)s->params.action_names[i]; 591 592 free((void *)name); 593 } 594 595 free(s->params.action_names); 596 s->params.action_names = NULL; 597 598 s->params.n_actions = 0; 599 600 default_action_name = (uintptr_t)s->params.default_action_name; 601 free((void *)default_action_name); 602 s->params.default_action_name = NULL; 603 604 default_action_args = (uintptr_t)s->params.default_action_args; 605 free((void *)default_action_args); 606 s->params.default_action_args = NULL; 607 608 free(s->params.action_is_for_table_entries); 609 s->params.action_is_for_table_entries = NULL; 610 611 free(s->params.action_is_for_default_entry); 612 s->params.action_is_for_default_entry = NULL; 613 614 s->params.default_action_is_const = 0; 615 616 free(s->recommended_table_type_name); 617 s->recommended_table_type_name = NULL; 618 619 free(s->args); 620 s->args = NULL; 621 622 s->size = 0; 623 } 624 625 static int 626 table_key_statement_parse(uint32_t *block_mask, 627 char **tokens, 628 uint32_t n_tokens, 629 uint32_t n_lines, 630 uint32_t *err_line, 631 const char **err_msg) 632 { 633 /* Check format. */ 634 if ((n_tokens != 2) || strcmp(tokens[1], "{")) { 635 if (err_line) 636 *err_line = n_lines; 637 if (err_msg) 638 *err_msg = "Invalid key statement."; 639 return -EINVAL; 640 } 641 642 /* block_mask. */ 643 *block_mask |= 1 << TABLE_KEY_BLOCK; 644 645 return 0; 646 } 647 648 static int 649 table_key_block_parse(struct table_spec *s, 650 uint32_t *block_mask, 651 char **tokens, 652 uint32_t n_tokens, 653 uint32_t n_lines, 654 uint32_t *err_line, 655 const char **err_msg) 656 { 657 struct rte_swx_match_field_params *new_fields; 658 enum rte_swx_table_match_type match_type = RTE_SWX_TABLE_MATCH_WILDCARD; 659 char *name; 660 661 /* Handle end of block. */ 662 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 663 *block_mask &= ~(1 << TABLE_KEY_BLOCK); 664 return 0; 665 } 666 667 /* Check input arguments. */ 668 if ((n_tokens != 2) || 669 (strcmp(tokens[1], "exact") && 670 strcmp(tokens[1], "wildcard") && 671 strcmp(tokens[1], "lpm"))) { 672 if (err_line) 673 *err_line = n_lines; 674 if (err_msg) 675 *err_msg = "Invalid match field statement."; 676 return -EINVAL; 677 } 678 679 if (!strcmp(tokens[1], "wildcard")) 680 match_type = RTE_SWX_TABLE_MATCH_WILDCARD; 681 if (!strcmp(tokens[1], "lpm")) 682 match_type = RTE_SWX_TABLE_MATCH_LPM; 683 if (!strcmp(tokens[1], "exact")) 684 match_type = RTE_SWX_TABLE_MATCH_EXACT; 685 686 name = strdup(tokens[0]); 687 if (!name) { 688 if (err_line) 689 *err_line = n_lines; 690 if (err_msg) 691 *err_msg = "Memory allocation failed."; 692 return -ENOMEM; 693 } 694 695 new_fields = realloc(s->params.fields, 696 (s->params.n_fields + 1) * sizeof(struct rte_swx_match_field_params)); 697 if (!new_fields) { 698 free(name); 699 700 if (err_line) 701 *err_line = n_lines; 702 if (err_msg) 703 *err_msg = "Memory allocation failed."; 704 return -ENOMEM; 705 } 706 707 s->params.fields = new_fields; 708 s->params.fields[s->params.n_fields].name = name; 709 s->params.fields[s->params.n_fields].match_type = match_type; 710 s->params.n_fields++; 711 712 return 0; 713 } 714 715 static int 716 table_actions_statement_parse(uint32_t *block_mask, 717 char **tokens, 718 uint32_t n_tokens, 719 uint32_t n_lines, 720 uint32_t *err_line, 721 const char **err_msg) 722 { 723 /* Check format. */ 724 if ((n_tokens != 2) || strcmp(tokens[1], "{")) { 725 if (err_line) 726 *err_line = n_lines; 727 if (err_msg) 728 *err_msg = "Invalid actions statement."; 729 return -EINVAL; 730 } 731 732 /* block_mask. */ 733 *block_mask |= 1 << TABLE_ACTIONS_BLOCK; 734 735 return 0; 736 } 737 738 static int 739 table_actions_block_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 const char **new_action_names = NULL; 748 int *new_action_is_for_table_entries = NULL, *new_action_is_for_default_entry = NULL; 749 char *name = NULL; 750 int action_is_for_table_entries = 1, action_is_for_default_entry = 1; 751 752 /* Handle end of block. */ 753 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 754 *block_mask &= ~(1 << TABLE_ACTIONS_BLOCK); 755 return 0; 756 } 757 758 /* Check input arguments. */ 759 if ((n_tokens > 2) || 760 ((n_tokens == 2) && strcmp(tokens[1], "@tableonly") && 761 strcmp(tokens[1], "@defaultonly"))) { 762 if (err_line) 763 *err_line = n_lines; 764 if (err_msg) 765 *err_msg = "Invalid action name statement."; 766 return -EINVAL; 767 } 768 769 name = strdup(tokens[0]); 770 771 if (n_tokens == 2) { 772 if (!strcmp(tokens[1], "@tableonly")) 773 action_is_for_default_entry = 0; 774 775 if (!strcmp(tokens[1], "@defaultonly")) 776 action_is_for_table_entries = 0; 777 } 778 779 new_action_names = realloc(s->params.action_names, 780 (s->params.n_actions + 1) * sizeof(char *)); 781 new_action_is_for_table_entries = realloc(s->params.action_is_for_table_entries, 782 (s->params.n_actions + 1) * sizeof(int)); 783 new_action_is_for_default_entry = realloc(s->params.action_is_for_default_entry, 784 (s->params.n_actions + 1) * sizeof(int)); 785 786 if (!name || 787 !new_action_names || 788 !new_action_is_for_table_entries || 789 !new_action_is_for_default_entry) { 790 free(name); 791 free(new_action_names); 792 free(new_action_is_for_table_entries); 793 free(new_action_is_for_default_entry); 794 795 if (err_line) 796 *err_line = n_lines; 797 if (err_msg) 798 *err_msg = "Memory allocation failed."; 799 return -ENOMEM; 800 } 801 802 s->params.action_names = new_action_names; 803 s->params.action_names[s->params.n_actions] = name; 804 805 s->params.action_is_for_table_entries = new_action_is_for_table_entries; 806 s->params.action_is_for_table_entries[s->params.n_actions] = action_is_for_table_entries; 807 808 s->params.action_is_for_default_entry = new_action_is_for_default_entry; 809 s->params.action_is_for_default_entry[s->params.n_actions] = action_is_for_default_entry; 810 811 s->params.n_actions++; 812 813 return 0; 814 } 815 816 static int 817 table_default_action_statement_parse(struct table_spec *s, 818 char **tokens, 819 uint32_t n_tokens, 820 uint32_t n_lines, 821 uint32_t *err_line, 822 const char **err_msg) 823 { 824 uint32_t i; 825 int status = 0, duplicate = 0; 826 827 /* Check format. */ 828 if ((n_tokens < 4) || 829 strcmp(tokens[2], "args")) { 830 status = -EINVAL; 831 goto error; 832 } 833 834 if (s->params.default_action_name) { 835 duplicate = 1; 836 status = -EINVAL; 837 goto error; 838 } 839 840 s->params.default_action_name = strdup(tokens[1]); 841 if (!s->params.default_action_name) { 842 status = -ENOMEM; 843 goto error; 844 } 845 846 if (strcmp(tokens[3], "none")) { 847 char buffer[MAX_LINE_LENGTH]; 848 uint32_t n_tokens_args = n_tokens - 3; 849 850 if (!strcmp(tokens[n_tokens - 1], "const")) 851 n_tokens_args--; 852 853 if (!n_tokens_args) { 854 status = -EINVAL; 855 goto error; 856 } 857 858 buffer[0] = 0; 859 for (i = 0; i < n_tokens_args; i++) { 860 if (i) 861 strcat(buffer, " "); 862 863 strcat(buffer, tokens[3 + i]); 864 } 865 866 s->params.default_action_args = strdup(buffer); 867 if (!s->params.default_action_args) { 868 status = -ENOMEM; 869 goto error; 870 } 871 } else { 872 if (((n_tokens != 4) && (n_tokens != 5)) || 873 ((n_tokens == 5) && (strcmp(tokens[4], "const")))) { 874 status = -EINVAL; 875 goto error; 876 } 877 } 878 879 if (!strcmp(tokens[n_tokens - 1], "const")) 880 s->params.default_action_is_const = 1; 881 882 return 0; 883 884 error: 885 if (err_line) 886 *err_line = n_lines; 887 888 if (err_msg) 889 switch (status) { 890 case -ENOMEM: 891 *err_msg = "Memory allocation failed."; 892 break; 893 894 default: 895 if (duplicate) 896 *err_msg = "Duplicate default_action statement."; 897 898 *err_msg = "Invalid default_action statement."; 899 } 900 901 return status; 902 } 903 904 static int 905 table_statement_parse(struct table_spec *s, 906 uint32_t *block_mask, 907 char **tokens, 908 uint32_t n_tokens, 909 uint32_t n_lines, 910 uint32_t *err_line, 911 const char **err_msg) 912 { 913 /* Check format. */ 914 if ((n_tokens != 3) || strcmp(tokens[2], "{")) { 915 if (err_line) 916 *err_line = n_lines; 917 if (err_msg) 918 *err_msg = "Invalid table statement."; 919 return -EINVAL; 920 } 921 922 /* spec. */ 923 s->name = strdup(tokens[1]); 924 if (!s->name) { 925 if (err_line) 926 *err_line = n_lines; 927 if (err_msg) 928 *err_msg = "Memory allocation failed."; 929 return -ENOMEM; 930 } 931 932 /* block_mask. */ 933 *block_mask |= 1 << TABLE_BLOCK; 934 935 return 0; 936 } 937 938 static int 939 table_block_parse(struct table_spec *s, 940 uint32_t *block_mask, 941 char **tokens, 942 uint32_t n_tokens, 943 uint32_t n_lines, 944 uint32_t *err_line, 945 const char **err_msg) 946 { 947 if (*block_mask & (1 << TABLE_KEY_BLOCK)) 948 return table_key_block_parse(s, 949 block_mask, 950 tokens, 951 n_tokens, 952 n_lines, 953 err_line, 954 err_msg); 955 956 if (*block_mask & (1 << TABLE_ACTIONS_BLOCK)) 957 return table_actions_block_parse(s, 958 block_mask, 959 tokens, 960 n_tokens, 961 n_lines, 962 err_line, 963 err_msg); 964 965 /* Handle end of block. */ 966 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 967 *block_mask &= ~(1 << TABLE_BLOCK); 968 return 0; 969 } 970 971 if (!strcmp(tokens[0], "key")) 972 return table_key_statement_parse(block_mask, 973 tokens, 974 n_tokens, 975 n_lines, 976 err_line, 977 err_msg); 978 979 if (!strcmp(tokens[0], "actions")) 980 return table_actions_statement_parse(block_mask, 981 tokens, 982 n_tokens, 983 n_lines, 984 err_line, 985 err_msg); 986 987 if (!strcmp(tokens[0], "default_action")) 988 return table_default_action_statement_parse(s, 989 tokens, 990 n_tokens, 991 n_lines, 992 err_line, 993 err_msg); 994 995 if (!strcmp(tokens[0], "instanceof")) { 996 if (n_tokens != 2) { 997 if (err_line) 998 *err_line = n_lines; 999 if (err_msg) 1000 *err_msg = "Invalid instanceof statement."; 1001 return -EINVAL; 1002 } 1003 1004 if (s->recommended_table_type_name) { 1005 if (err_line) 1006 *err_line = n_lines; 1007 if (err_msg) 1008 *err_msg = "Duplicate instanceof statement."; 1009 return -EINVAL; 1010 } 1011 1012 s->recommended_table_type_name = strdup(tokens[1]); 1013 if (!s->recommended_table_type_name) { 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], "pragma")) { 1025 if (n_tokens != 2) { 1026 if (err_line) 1027 *err_line = n_lines; 1028 if (err_msg) 1029 *err_msg = "Invalid pragma statement."; 1030 return -EINVAL; 1031 } 1032 1033 if (s->args) { 1034 if (err_line) 1035 *err_line = n_lines; 1036 if (err_msg) 1037 *err_msg = "Duplicate pragma statement."; 1038 return -EINVAL; 1039 } 1040 1041 s->args = strdup(tokens[1]); 1042 if (!s->args) { 1043 if (err_line) 1044 *err_line = n_lines; 1045 if (err_msg) 1046 *err_msg = "Memory allocation failed."; 1047 return -ENOMEM; 1048 } 1049 1050 return 0; 1051 } 1052 1053 if (!strcmp(tokens[0], "size")) { 1054 char *p = tokens[1]; 1055 1056 if (n_tokens != 2) { 1057 if (err_line) 1058 *err_line = n_lines; 1059 if (err_msg) 1060 *err_msg = "Invalid pragma statement."; 1061 return -EINVAL; 1062 } 1063 1064 s->size = strtoul(p, &p, 0); 1065 if (p[0]) { 1066 if (err_line) 1067 *err_line = n_lines; 1068 if (err_msg) 1069 *err_msg = "Invalid size argument."; 1070 return -EINVAL; 1071 } 1072 1073 return 0; 1074 } 1075 1076 /* Anything else. */ 1077 if (err_line) 1078 *err_line = n_lines; 1079 if (err_msg) 1080 *err_msg = "Invalid statement."; 1081 return -EINVAL; 1082 } 1083 1084 /* 1085 * selector. 1086 * 1087 * selector SELECTOR_NAME { 1088 * group_id FIELD_NAME 1089 * selector { 1090 * FIELD_NAME 1091 * ... 1092 * } 1093 * member_id FIELD_NAME 1094 * n_groups N_GROUPS 1095 * n_members_per_group N_MEMBERS_PER_GROUP 1096 * } 1097 */ 1098 struct selector_spec { 1099 char *name; 1100 struct rte_swx_pipeline_selector_params params; 1101 }; 1102 1103 static void 1104 selector_spec_free(struct selector_spec *s) 1105 { 1106 uintptr_t field_name; 1107 uint32_t i; 1108 1109 if (!s) 1110 return; 1111 1112 /* name. */ 1113 free(s->name); 1114 s->name = NULL; 1115 1116 /* params->group_id_field_name. */ 1117 field_name = (uintptr_t)s->params.group_id_field_name; 1118 free((void *)field_name); 1119 s->params.group_id_field_name = NULL; 1120 1121 /* params->selector_field_names. */ 1122 for (i = 0; i < s->params.n_selector_fields; i++) { 1123 field_name = (uintptr_t)s->params.selector_field_names[i]; 1124 1125 free((void *)field_name); 1126 } 1127 1128 free(s->params.selector_field_names); 1129 s->params.selector_field_names = NULL; 1130 1131 s->params.n_selector_fields = 0; 1132 1133 /* params->member_id_field_name. */ 1134 field_name = (uintptr_t)s->params.member_id_field_name; 1135 free((void *)field_name); 1136 s->params.member_id_field_name = NULL; 1137 1138 /* params->n_groups_max. */ 1139 s->params.n_groups_max = 0; 1140 1141 /* params->n_members_per_group_max. */ 1142 s->params.n_members_per_group_max = 0; 1143 } 1144 1145 static int 1146 selector_statement_parse(struct selector_spec *s, 1147 uint32_t *block_mask, 1148 char **tokens, 1149 uint32_t n_tokens, 1150 uint32_t n_lines, 1151 uint32_t *err_line, 1152 const char **err_msg) 1153 { 1154 /* Check format. */ 1155 if ((n_tokens != 3) || strcmp(tokens[2], "{")) { 1156 if (err_line) 1157 *err_line = n_lines; 1158 if (err_msg) 1159 *err_msg = "Invalid selector statement."; 1160 return -EINVAL; 1161 } 1162 1163 /* spec. */ 1164 s->name = strdup(tokens[1]); 1165 if (!s->name) { 1166 if (err_line) 1167 *err_line = n_lines; 1168 if (err_msg) 1169 *err_msg = "Memory allocation failed."; 1170 return -ENOMEM; 1171 } 1172 1173 /* block_mask. */ 1174 *block_mask |= 1 << SELECTOR_BLOCK; 1175 1176 return 0; 1177 } 1178 1179 static int 1180 selector_selector_statement_parse(uint32_t *block_mask, 1181 char **tokens, 1182 uint32_t n_tokens, 1183 uint32_t n_lines, 1184 uint32_t *err_line, 1185 const char **err_msg) 1186 { 1187 /* Check format. */ 1188 if ((n_tokens != 2) || strcmp(tokens[1], "{")) { 1189 if (err_line) 1190 *err_line = n_lines; 1191 if (err_msg) 1192 *err_msg = "Invalid selector statement."; 1193 return -EINVAL; 1194 } 1195 1196 /* block_mask. */ 1197 *block_mask |= 1 << SELECTOR_SELECTOR_BLOCK; 1198 1199 return 0; 1200 } 1201 1202 static int 1203 selector_selector_block_parse(struct selector_spec *s, 1204 uint32_t *block_mask, 1205 char **tokens, 1206 uint32_t n_tokens, 1207 uint32_t n_lines, 1208 uint32_t *err_line, 1209 const char **err_msg) 1210 { 1211 const char **new_fields; 1212 char *name; 1213 1214 /* Handle end of block. */ 1215 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 1216 *block_mask &= ~(1 << SELECTOR_SELECTOR_BLOCK); 1217 return 0; 1218 } 1219 1220 /* Check input arguments. */ 1221 if (n_tokens != 1) { 1222 if (err_line) 1223 *err_line = n_lines; 1224 if (err_msg) 1225 *err_msg = "Invalid selector field statement."; 1226 return -EINVAL; 1227 } 1228 1229 name = strdup(tokens[0]); 1230 if (!name) { 1231 if (err_line) 1232 *err_line = n_lines; 1233 if (err_msg) 1234 *err_msg = "Memory allocation failed."; 1235 return -ENOMEM; 1236 } 1237 1238 new_fields = realloc(s->params.selector_field_names, 1239 (s->params.n_selector_fields + 1) * sizeof(char *)); 1240 if (!new_fields) { 1241 free(name); 1242 1243 if (err_line) 1244 *err_line = n_lines; 1245 if (err_msg) 1246 *err_msg = "Memory allocation failed."; 1247 return -ENOMEM; 1248 } 1249 1250 s->params.selector_field_names = new_fields; 1251 s->params.selector_field_names[s->params.n_selector_fields] = name; 1252 s->params.n_selector_fields++; 1253 1254 return 0; 1255 } 1256 1257 static int 1258 selector_block_parse(struct selector_spec *s, 1259 uint32_t *block_mask, 1260 char **tokens, 1261 uint32_t n_tokens, 1262 uint32_t n_lines, 1263 uint32_t *err_line, 1264 const char **err_msg) 1265 { 1266 if (*block_mask & (1 << SELECTOR_SELECTOR_BLOCK)) 1267 return selector_selector_block_parse(s, 1268 block_mask, 1269 tokens, 1270 n_tokens, 1271 n_lines, 1272 err_line, 1273 err_msg); 1274 1275 /* Handle end of block. */ 1276 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 1277 *block_mask &= ~(1 << SELECTOR_BLOCK); 1278 return 0; 1279 } 1280 1281 if (!strcmp(tokens[0], "group_id")) { 1282 if (n_tokens != 2) { 1283 if (err_line) 1284 *err_line = n_lines; 1285 if (err_msg) 1286 *err_msg = "Invalid group_id statement."; 1287 return -EINVAL; 1288 } 1289 1290 s->params.group_id_field_name = strdup(tokens[1]); 1291 if (!s->params.group_id_field_name) { 1292 if (err_line) 1293 *err_line = n_lines; 1294 if (err_msg) 1295 *err_msg = "Memory allocation failed."; 1296 return -ENOMEM; 1297 } 1298 1299 return 0; 1300 } 1301 1302 if (!strcmp(tokens[0], "selector")) 1303 return selector_selector_statement_parse(block_mask, 1304 tokens, 1305 n_tokens, 1306 n_lines, 1307 err_line, 1308 err_msg); 1309 1310 if (!strcmp(tokens[0], "member_id")) { 1311 if (n_tokens != 2) { 1312 if (err_line) 1313 *err_line = n_lines; 1314 if (err_msg) 1315 *err_msg = "Invalid member_id statement."; 1316 return -EINVAL; 1317 } 1318 1319 s->params.member_id_field_name = strdup(tokens[1]); 1320 if (!s->params.member_id_field_name) { 1321 if (err_line) 1322 *err_line = n_lines; 1323 if (err_msg) 1324 *err_msg = "Memory allocation failed."; 1325 return -ENOMEM; 1326 } 1327 1328 return 0; 1329 } 1330 1331 if (!strcmp(tokens[0], "n_groups_max")) { 1332 char *p = tokens[1]; 1333 1334 if (n_tokens != 2) { 1335 if (err_line) 1336 *err_line = n_lines; 1337 if (err_msg) 1338 *err_msg = "Invalid n_groups statement."; 1339 return -EINVAL; 1340 } 1341 1342 s->params.n_groups_max = strtoul(p, &p, 0); 1343 if (p[0]) { 1344 if (err_line) 1345 *err_line = n_lines; 1346 if (err_msg) 1347 *err_msg = "Invalid n_groups argument."; 1348 return -EINVAL; 1349 } 1350 1351 return 0; 1352 } 1353 1354 if (!strcmp(tokens[0], "n_members_per_group_max")) { 1355 char *p = tokens[1]; 1356 1357 if (n_tokens != 2) { 1358 if (err_line) 1359 *err_line = n_lines; 1360 if (err_msg) 1361 *err_msg = "Invalid n_members_per_group statement."; 1362 return -EINVAL; 1363 } 1364 1365 s->params.n_members_per_group_max = strtoul(p, &p, 0); 1366 if (p[0]) { 1367 if (err_line) 1368 *err_line = n_lines; 1369 if (err_msg) 1370 *err_msg = "Invalid n_members_per_group argument."; 1371 return -EINVAL; 1372 } 1373 1374 return 0; 1375 } 1376 1377 /* Anything else. */ 1378 if (err_line) 1379 *err_line = n_lines; 1380 if (err_msg) 1381 *err_msg = "Invalid statement."; 1382 return -EINVAL; 1383 } 1384 1385 /* 1386 * learner. 1387 * 1388 * learner LEARNER_NAME { 1389 * key { 1390 * MATCH_FIELD_NAME 1391 * ... 1392 * } 1393 * actions { 1394 * ACTION_NAME [ @tableonly | @defaultonly] 1395 * ... 1396 * } 1397 * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ] 1398 * size SIZE 1399 * timeout { 1400 * TIMEOUT_IN_SECONDS 1401 * ... 1402 * } 1403 * } 1404 */ 1405 struct learner_spec { 1406 char *name; 1407 struct rte_swx_pipeline_learner_params params; 1408 uint32_t size; 1409 uint32_t *timeout; 1410 uint32_t n_timeouts; 1411 }; 1412 1413 static void 1414 learner_spec_free(struct learner_spec *s) 1415 { 1416 uintptr_t default_action_name, default_action_args; 1417 uint32_t i; 1418 1419 if (!s) 1420 return; 1421 1422 free(s->name); 1423 s->name = NULL; 1424 1425 for (i = 0; i < s->params.n_fields; i++) { 1426 uintptr_t name = (uintptr_t)s->params.field_names[i]; 1427 1428 free((void *)name); 1429 } 1430 1431 free(s->params.field_names); 1432 s->params.field_names = NULL; 1433 1434 s->params.n_fields = 0; 1435 1436 for (i = 0; i < s->params.n_actions; i++) { 1437 uintptr_t name = (uintptr_t)s->params.action_names[i]; 1438 1439 free((void *)name); 1440 } 1441 1442 free(s->params.action_names); 1443 s->params.action_names = NULL; 1444 1445 s->params.n_actions = 0; 1446 1447 default_action_name = (uintptr_t)s->params.default_action_name; 1448 free((void *)default_action_name); 1449 s->params.default_action_name = NULL; 1450 1451 default_action_args = (uintptr_t)s->params.default_action_args; 1452 free((void *)default_action_args); 1453 s->params.default_action_args = NULL; 1454 1455 free(s->params.action_is_for_table_entries); 1456 s->params.action_is_for_table_entries = NULL; 1457 1458 free(s->params.action_is_for_default_entry); 1459 s->params.action_is_for_default_entry = NULL; 1460 1461 s->params.default_action_is_const = 0; 1462 1463 s->size = 0; 1464 1465 free(s->timeout); 1466 s->timeout = NULL; 1467 1468 s->n_timeouts = 0; 1469 } 1470 1471 static int 1472 learner_key_statement_parse(uint32_t *block_mask, 1473 char **tokens, 1474 uint32_t n_tokens, 1475 uint32_t n_lines, 1476 uint32_t *err_line, 1477 const char **err_msg) 1478 { 1479 /* Check format. */ 1480 if ((n_tokens != 2) || strcmp(tokens[1], "{")) { 1481 if (err_line) 1482 *err_line = n_lines; 1483 if (err_msg) 1484 *err_msg = "Invalid key statement."; 1485 return -EINVAL; 1486 } 1487 1488 /* block_mask. */ 1489 *block_mask |= 1 << LEARNER_KEY_BLOCK; 1490 1491 return 0; 1492 } 1493 1494 static int 1495 learner_key_block_parse(struct learner_spec *s, 1496 uint32_t *block_mask, 1497 char **tokens, 1498 uint32_t n_tokens, 1499 uint32_t n_lines, 1500 uint32_t *err_line, 1501 const char **err_msg) 1502 { 1503 const char **new_field_names = NULL; 1504 char *field_name = NULL; 1505 1506 /* Handle end of block. */ 1507 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 1508 *block_mask &= ~(1 << LEARNER_KEY_BLOCK); 1509 return 0; 1510 } 1511 1512 /* Check input arguments. */ 1513 if (n_tokens != 1) { 1514 if (err_line) 1515 *err_line = n_lines; 1516 if (err_msg) 1517 *err_msg = "Invalid match field statement."; 1518 return -EINVAL; 1519 } 1520 1521 field_name = strdup(tokens[0]); 1522 new_field_names = realloc(s->params.field_names, (s->params.n_fields + 1) * sizeof(char *)); 1523 if (!field_name || !new_field_names) { 1524 free(field_name); 1525 free(new_field_names); 1526 1527 if (err_line) 1528 *err_line = n_lines; 1529 if (err_msg) 1530 *err_msg = "Memory allocation failed."; 1531 return -ENOMEM; 1532 } 1533 1534 s->params.field_names = new_field_names; 1535 s->params.field_names[s->params.n_fields] = field_name; 1536 s->params.n_fields++; 1537 1538 return 0; 1539 } 1540 1541 static int 1542 learner_actions_statement_parse(uint32_t *block_mask, 1543 char **tokens, 1544 uint32_t n_tokens, 1545 uint32_t n_lines, 1546 uint32_t *err_line, 1547 const char **err_msg) 1548 { 1549 /* Check format. */ 1550 if ((n_tokens != 2) || strcmp(tokens[1], "{")) { 1551 if (err_line) 1552 *err_line = n_lines; 1553 if (err_msg) 1554 *err_msg = "Invalid actions statement."; 1555 return -EINVAL; 1556 } 1557 1558 /* block_mask. */ 1559 *block_mask |= 1 << LEARNER_ACTIONS_BLOCK; 1560 1561 return 0; 1562 } 1563 1564 static int 1565 learner_actions_block_parse(struct learner_spec *s, 1566 uint32_t *block_mask, 1567 char **tokens, 1568 uint32_t n_tokens, 1569 uint32_t n_lines, 1570 uint32_t *err_line, 1571 const char **err_msg) 1572 { 1573 const char **new_action_names = NULL; 1574 int *new_action_is_for_table_entries = NULL, *new_action_is_for_default_entry = NULL; 1575 char *name = NULL; 1576 int action_is_for_table_entries = 1, action_is_for_default_entry = 1; 1577 1578 /* Handle end of block. */ 1579 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 1580 *block_mask &= ~(1 << LEARNER_ACTIONS_BLOCK); 1581 return 0; 1582 } 1583 1584 /* Check input arguments. */ 1585 if ((n_tokens > 2) || 1586 ((n_tokens == 2) && strcmp(tokens[1], "@tableonly") && 1587 strcmp(tokens[1], "@defaultonly"))) { 1588 if (err_line) 1589 *err_line = n_lines; 1590 if (err_msg) 1591 *err_msg = "Invalid action name statement."; 1592 return -EINVAL; 1593 } 1594 1595 name = strdup(tokens[0]); 1596 1597 if (n_tokens == 2) { 1598 if (!strcmp(tokens[1], "@tableonly")) 1599 action_is_for_default_entry = 0; 1600 1601 if (!strcmp(tokens[1], "@defaultonly")) 1602 action_is_for_table_entries = 0; 1603 } 1604 1605 new_action_names = realloc(s->params.action_names, 1606 (s->params.n_actions + 1) * sizeof(char *)); 1607 new_action_is_for_table_entries = realloc(s->params.action_is_for_table_entries, 1608 (s->params.n_actions + 1) * sizeof(int)); 1609 new_action_is_for_default_entry = realloc(s->params.action_is_for_default_entry, 1610 (s->params.n_actions + 1) * sizeof(int)); 1611 1612 if (!name || 1613 !new_action_names || 1614 !new_action_is_for_table_entries || 1615 !new_action_is_for_default_entry) { 1616 free(name); 1617 free(new_action_names); 1618 free(new_action_is_for_table_entries); 1619 free(new_action_is_for_default_entry); 1620 1621 if (err_line) 1622 *err_line = n_lines; 1623 if (err_msg) 1624 *err_msg = "Memory allocation failed."; 1625 return -ENOMEM; 1626 } 1627 1628 s->params.action_names = new_action_names; 1629 s->params.action_names[s->params.n_actions] = name; 1630 1631 s->params.action_is_for_table_entries = new_action_is_for_table_entries; 1632 s->params.action_is_for_table_entries[s->params.n_actions] = action_is_for_table_entries; 1633 1634 s->params.action_is_for_default_entry = new_action_is_for_default_entry; 1635 s->params.action_is_for_default_entry[s->params.n_actions] = action_is_for_default_entry; 1636 1637 s->params.n_actions++; 1638 1639 return 0; 1640 } 1641 1642 static int 1643 learner_default_action_statement_parse(struct learner_spec *s, 1644 char **tokens, 1645 uint32_t n_tokens, 1646 uint32_t n_lines, 1647 uint32_t *err_line, 1648 const char **err_msg) 1649 { 1650 uint32_t i; 1651 int status = 0, duplicate = 0; 1652 1653 /* Check format. */ 1654 if ((n_tokens < 4) || 1655 strcmp(tokens[2], "args")) { 1656 status = -EINVAL; 1657 goto error; 1658 } 1659 1660 if (s->params.default_action_name) { 1661 duplicate = 1; 1662 status = -EINVAL; 1663 goto error; 1664 } 1665 1666 s->params.default_action_name = strdup(tokens[1]); 1667 if (!s->params.default_action_name) { 1668 status = -ENOMEM; 1669 goto error; 1670 } 1671 1672 if (strcmp(tokens[3], "none")) { 1673 char buffer[MAX_LINE_LENGTH]; 1674 uint32_t n_tokens_args = n_tokens - 3; 1675 1676 if (!strcmp(tokens[n_tokens - 1], "const")) 1677 n_tokens_args--; 1678 1679 if (!n_tokens_args) { 1680 status = -EINVAL; 1681 goto error; 1682 } 1683 1684 buffer[0] = 0; 1685 for (i = 0; i < n_tokens_args; i++) { 1686 if (i) 1687 strcat(buffer, " "); 1688 1689 strcat(buffer, tokens[3 + i]); 1690 } 1691 1692 s->params.default_action_args = strdup(buffer); 1693 if (!s->params.default_action_args) { 1694 status = -ENOMEM; 1695 goto error; 1696 } 1697 } else { 1698 if (((n_tokens != 4) && (n_tokens != 5)) || 1699 ((n_tokens == 5) && (strcmp(tokens[4], "const")))) { 1700 status = -EINVAL; 1701 goto error; 1702 } 1703 } 1704 1705 if (!strcmp(tokens[n_tokens - 1], "const")) 1706 s->params.default_action_is_const = 1; 1707 1708 return 0; 1709 1710 error: 1711 if (err_line) 1712 *err_line = n_lines; 1713 1714 if (err_msg) 1715 switch (status) { 1716 case -ENOMEM: 1717 *err_msg = "Memory allocation failed."; 1718 break; 1719 1720 default: 1721 if (duplicate) 1722 *err_msg = "Duplicate default_action statement."; 1723 1724 *err_msg = "Invalid default_action statement."; 1725 } 1726 1727 return status; 1728 } 1729 1730 static int 1731 learner_timeout_statement_parse(uint32_t *block_mask, 1732 char **tokens, 1733 uint32_t n_tokens, 1734 uint32_t n_lines, 1735 uint32_t *err_line, 1736 const char **err_msg) 1737 { 1738 /* Check format. */ 1739 if ((n_tokens != 2) || strcmp(tokens[1], "{")) { 1740 if (err_line) 1741 *err_line = n_lines; 1742 if (err_msg) 1743 *err_msg = "Invalid timeout statement."; 1744 return -EINVAL; 1745 } 1746 1747 /* block_mask. */ 1748 *block_mask |= 1 << LEARNER_TIMEOUT_BLOCK; 1749 1750 return 0; 1751 } 1752 1753 static int 1754 learner_timeout_block_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 uint32_t *new_timeout = NULL; 1763 char *str; 1764 uint32_t val; 1765 int status = 0; 1766 1767 /* Handle end of block. */ 1768 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 1769 *block_mask &= ~(1 << LEARNER_TIMEOUT_BLOCK); 1770 return 0; 1771 } 1772 1773 /* Check input arguments. */ 1774 if (n_tokens != 1) { 1775 status = -EINVAL; 1776 goto error; 1777 } 1778 1779 str = tokens[0]; 1780 val = strtoul(str, &str, 0); 1781 if (str[0]) { 1782 status = -EINVAL; 1783 goto error; 1784 } 1785 1786 new_timeout = realloc(s->timeout, (s->n_timeouts + 1) * sizeof(uint32_t)); 1787 if (!new_timeout) { 1788 status = -ENOMEM; 1789 goto error; 1790 } 1791 1792 s->timeout = new_timeout; 1793 s->timeout[s->n_timeouts] = val; 1794 s->n_timeouts++; 1795 1796 return 0; 1797 1798 error: 1799 free(new_timeout); 1800 1801 if (err_line) 1802 *err_line = n_lines; 1803 1804 if (err_msg) 1805 switch (status) { 1806 case -ENOMEM: 1807 *err_msg = "Memory allocation failed."; 1808 break; 1809 1810 default: 1811 *err_msg = "Invalid timeout value statement."; 1812 break; 1813 } 1814 1815 return status; 1816 } 1817 1818 1819 static int 1820 learner_statement_parse(struct learner_spec *s, 1821 uint32_t *block_mask, 1822 char **tokens, 1823 uint32_t n_tokens, 1824 uint32_t n_lines, 1825 uint32_t *err_line, 1826 const char **err_msg) 1827 { 1828 /* Check format. */ 1829 if ((n_tokens != 3) || strcmp(tokens[2], "{")) { 1830 if (err_line) 1831 *err_line = n_lines; 1832 if (err_msg) 1833 *err_msg = "Invalid learner statement."; 1834 return -EINVAL; 1835 } 1836 1837 /* spec. */ 1838 s->name = strdup(tokens[1]); 1839 if (!s->name) { 1840 if (err_line) 1841 *err_line = n_lines; 1842 if (err_msg) 1843 *err_msg = "Memory allocation failed."; 1844 return -ENOMEM; 1845 } 1846 1847 /* block_mask. */ 1848 *block_mask |= 1 << LEARNER_BLOCK; 1849 1850 return 0; 1851 } 1852 1853 static int 1854 learner_block_parse(struct learner_spec *s, 1855 uint32_t *block_mask, 1856 char **tokens, 1857 uint32_t n_tokens, 1858 uint32_t n_lines, 1859 uint32_t *err_line, 1860 const char **err_msg) 1861 { 1862 if (*block_mask & (1 << LEARNER_KEY_BLOCK)) 1863 return learner_key_block_parse(s, 1864 block_mask, 1865 tokens, 1866 n_tokens, 1867 n_lines, 1868 err_line, 1869 err_msg); 1870 1871 if (*block_mask & (1 << LEARNER_ACTIONS_BLOCK)) 1872 return learner_actions_block_parse(s, 1873 block_mask, 1874 tokens, 1875 n_tokens, 1876 n_lines, 1877 err_line, 1878 err_msg); 1879 1880 if (*block_mask & (1 << LEARNER_TIMEOUT_BLOCK)) 1881 return learner_timeout_block_parse(s, 1882 block_mask, 1883 tokens, 1884 n_tokens, 1885 n_lines, 1886 err_line, 1887 err_msg); 1888 1889 /* Handle end of block. */ 1890 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 1891 *block_mask &= ~(1 << LEARNER_BLOCK); 1892 return 0; 1893 } 1894 1895 if (!strcmp(tokens[0], "key")) 1896 return learner_key_statement_parse(block_mask, 1897 tokens, 1898 n_tokens, 1899 n_lines, 1900 err_line, 1901 err_msg); 1902 1903 if (!strcmp(tokens[0], "actions")) 1904 return learner_actions_statement_parse(block_mask, 1905 tokens, 1906 n_tokens, 1907 n_lines, 1908 err_line, 1909 err_msg); 1910 1911 if (!strcmp(tokens[0], "default_action")) 1912 return learner_default_action_statement_parse(s, 1913 tokens, 1914 n_tokens, 1915 n_lines, 1916 err_line, 1917 err_msg); 1918 1919 if (!strcmp(tokens[0], "size")) { 1920 char *p = tokens[1]; 1921 1922 if (n_tokens != 2) { 1923 if (err_line) 1924 *err_line = n_lines; 1925 if (err_msg) 1926 *err_msg = "Invalid size statement."; 1927 return -EINVAL; 1928 } 1929 1930 s->size = strtoul(p, &p, 0); 1931 if (p[0]) { 1932 if (err_line) 1933 *err_line = n_lines; 1934 if (err_msg) 1935 *err_msg = "Invalid size argument."; 1936 return -EINVAL; 1937 } 1938 1939 return 0; 1940 } 1941 1942 if (!strcmp(tokens[0], "timeout")) 1943 return learner_timeout_statement_parse(block_mask, 1944 tokens, 1945 n_tokens, 1946 n_lines, 1947 err_line, 1948 err_msg); 1949 1950 /* Anything else. */ 1951 if (err_line) 1952 *err_line = n_lines; 1953 if (err_msg) 1954 *err_msg = "Invalid statement."; 1955 return -EINVAL; 1956 } 1957 1958 /* 1959 * regarray. 1960 * 1961 * regarray NAME size SIZE initval INITVAL 1962 */ 1963 struct regarray_spec { 1964 char *name; 1965 uint64_t init_val; 1966 uint32_t size; 1967 }; 1968 1969 static void 1970 regarray_spec_free(struct regarray_spec *s) 1971 { 1972 if (!s) 1973 return; 1974 1975 free(s->name); 1976 s->name = NULL; 1977 } 1978 1979 static int 1980 regarray_statement_parse(struct regarray_spec *s, 1981 char **tokens, 1982 uint32_t n_tokens, 1983 uint32_t n_lines, 1984 uint32_t *err_line, 1985 const char **err_msg) 1986 { 1987 char *p; 1988 1989 /* Check format. */ 1990 if ((n_tokens != 6) || 1991 strcmp(tokens[2], "size") || 1992 strcmp(tokens[4], "initval")) { 1993 if (err_line) 1994 *err_line = n_lines; 1995 if (err_msg) 1996 *err_msg = "Invalid regarray statement."; 1997 return -EINVAL; 1998 } 1999 2000 /* spec. */ 2001 s->name = strdup(tokens[1]); 2002 if (!s->name) { 2003 if (err_line) 2004 *err_line = n_lines; 2005 if (err_msg) 2006 *err_msg = "Memory allocation failed."; 2007 return -ENOMEM; 2008 } 2009 2010 p = tokens[3]; 2011 s->size = strtoul(p, &p, 0); 2012 if (p[0] || !s->size) { 2013 if (err_line) 2014 *err_line = n_lines; 2015 if (err_msg) 2016 *err_msg = "Invalid size argument."; 2017 return -EINVAL; 2018 } 2019 2020 p = tokens[5]; 2021 s->init_val = strtoull(p, &p, 0); 2022 if (p[0]) { 2023 if (err_line) 2024 *err_line = n_lines; 2025 if (err_msg) 2026 *err_msg = "Invalid initval argument."; 2027 return -EINVAL; 2028 } 2029 2030 return 0; 2031 } 2032 2033 /* 2034 * metarray. 2035 * 2036 * metarray NAME size SIZE 2037 */ 2038 struct metarray_spec { 2039 char *name; 2040 uint32_t size; 2041 }; 2042 2043 static void 2044 metarray_spec_free(struct metarray_spec *s) 2045 { 2046 if (!s) 2047 return; 2048 2049 free(s->name); 2050 s->name = NULL; 2051 } 2052 2053 static int 2054 metarray_statement_parse(struct metarray_spec *s, 2055 char **tokens, 2056 uint32_t n_tokens, 2057 uint32_t n_lines, 2058 uint32_t *err_line, 2059 const char **err_msg) 2060 { 2061 char *p; 2062 2063 /* Check format. */ 2064 if ((n_tokens != 4) || strcmp(tokens[2], "size")) { 2065 if (err_line) 2066 *err_line = n_lines; 2067 if (err_msg) 2068 *err_msg = "Invalid metarray statement."; 2069 return -EINVAL; 2070 } 2071 2072 /* spec. */ 2073 s->name = strdup(tokens[1]); 2074 if (!s->name) { 2075 if (err_line) 2076 *err_line = n_lines; 2077 if (err_msg) 2078 *err_msg = "Memory allocation failed."; 2079 return -ENOMEM; 2080 } 2081 2082 p = tokens[3]; 2083 s->size = strtoul(p, &p, 0); 2084 if (p[0] || !s->size) { 2085 if (err_line) 2086 *err_line = n_lines; 2087 if (err_msg) 2088 *err_msg = "Invalid size argument."; 2089 return -EINVAL; 2090 } 2091 2092 return 0; 2093 } 2094 2095 /* 2096 * apply. 2097 * 2098 * apply { 2099 * INSTRUCTION 2100 * ... 2101 * } 2102 */ 2103 struct apply_spec { 2104 const char **instructions; 2105 uint32_t n_instructions; 2106 }; 2107 2108 static void 2109 apply_spec_free(struct apply_spec *s) 2110 { 2111 uint32_t i; 2112 2113 if (!s) 2114 return; 2115 2116 for (i = 0; i < s->n_instructions; i++) { 2117 uintptr_t instr = (uintptr_t)s->instructions[i]; 2118 2119 free((void *)instr); 2120 } 2121 2122 free(s->instructions); 2123 s->instructions = NULL; 2124 2125 s->n_instructions = 0; 2126 } 2127 2128 static int 2129 apply_statement_parse(uint32_t *block_mask, 2130 char **tokens, 2131 uint32_t n_tokens, 2132 uint32_t n_lines, 2133 uint32_t *err_line, 2134 const char **err_msg) 2135 { 2136 /* Check format. */ 2137 if ((n_tokens != 2) || strcmp(tokens[1], "{")) { 2138 if (err_line) 2139 *err_line = n_lines; 2140 if (err_msg) 2141 *err_msg = "Invalid apply statement."; 2142 return -EINVAL; 2143 } 2144 2145 /* block_mask. */ 2146 *block_mask |= 1 << APPLY_BLOCK; 2147 2148 return 0; 2149 } 2150 2151 static int 2152 apply_block_parse(struct apply_spec *s, 2153 uint32_t *block_mask, 2154 char **tokens, 2155 uint32_t n_tokens, 2156 uint32_t n_lines, 2157 uint32_t *err_line, 2158 const char **err_msg) 2159 { 2160 char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr; 2161 const char **new_instructions; 2162 uint32_t i; 2163 2164 /* Handle end of block. */ 2165 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 2166 *block_mask &= ~(1 << APPLY_BLOCK); 2167 return 0; 2168 } 2169 2170 /* spec. */ 2171 buffer[0] = 0; 2172 for (i = 0; i < n_tokens; i++) { 2173 if (i) 2174 strcat(buffer, " "); 2175 strcat(buffer, tokens[i]); 2176 } 2177 2178 instr = strdup(buffer); 2179 if (!instr) { 2180 if (err_line) 2181 *err_line = n_lines; 2182 if (err_msg) 2183 *err_msg = "Memory allocation failed."; 2184 return -ENOMEM; 2185 } 2186 2187 new_instructions = realloc(s->instructions, 2188 (s->n_instructions + 1) * sizeof(char *)); 2189 if (!new_instructions) { 2190 free(instr); 2191 2192 if (err_line) 2193 *err_line = n_lines; 2194 if (err_msg) 2195 *err_msg = "Memory allocation failed."; 2196 return -ENOMEM; 2197 } 2198 2199 s->instructions = new_instructions; 2200 s->instructions[s->n_instructions] = instr; 2201 s->n_instructions++; 2202 2203 return 0; 2204 } 2205 2206 /* 2207 * Pipeline. 2208 */ 2209 int 2210 rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p, 2211 FILE *spec, 2212 uint32_t *err_line, 2213 const char **err_msg) 2214 { 2215 struct extobj_spec extobj_spec = {0}; 2216 struct struct_spec struct_spec = {0}; 2217 struct header_spec header_spec = {0}; 2218 struct metadata_spec metadata_spec = {0}; 2219 struct action_spec action_spec = {0}; 2220 struct table_spec table_spec = {0}; 2221 struct selector_spec selector_spec = {0}; 2222 struct learner_spec learner_spec = {0}; 2223 struct regarray_spec regarray_spec = {0}; 2224 struct metarray_spec metarray_spec = {0}; 2225 struct apply_spec apply_spec = {0}; 2226 uint32_t n_lines; 2227 uint32_t block_mask = 0; 2228 int status; 2229 2230 /* Check the input arguments. */ 2231 if (!p) { 2232 if (err_line) 2233 *err_line = 0; 2234 if (err_msg) 2235 *err_msg = "Null pipeline argument."; 2236 status = -EINVAL; 2237 goto error; 2238 } 2239 2240 if (!spec) { 2241 if (err_line) 2242 *err_line = 0; 2243 if (err_msg) 2244 *err_msg = "Null specification file argument."; 2245 status = -EINVAL; 2246 goto error; 2247 } 2248 2249 for (n_lines = 1; ; n_lines++) { 2250 char line[MAX_LINE_LENGTH]; 2251 char *tokens[MAX_TOKENS], *ptr = line; 2252 uint32_t n_tokens = 0; 2253 2254 /* Read next line. */ 2255 if (!fgets(line, sizeof(line), spec)) 2256 break; 2257 2258 /* Parse the line into tokens. */ 2259 for ( ; ; ) { 2260 char *token; 2261 2262 /* Get token. */ 2263 token = strtok_r(ptr, " \f\n\r\t\v", &ptr); 2264 if (!token) 2265 break; 2266 2267 /* Handle comments. */ 2268 if ((token[0] == '#') || 2269 (token[0] == ';') || 2270 ((token[0] == '/') && (token[1] == '/'))) { 2271 break; 2272 } 2273 2274 /* Handle excessively long lines. */ 2275 if (n_tokens >= RTE_DIM(tokens)) { 2276 if (err_line) 2277 *err_line = n_lines; 2278 if (err_msg) 2279 *err_msg = "Too many tokens."; 2280 status = -EINVAL; 2281 goto error; 2282 } 2283 2284 /* Handle excessively long tokens. */ 2285 if (strnlen(token, RTE_SWX_NAME_SIZE) >= 2286 RTE_SWX_NAME_SIZE) { 2287 if (err_line) 2288 *err_line = n_lines; 2289 if (err_msg) 2290 *err_msg = "Token too big."; 2291 status = -EINVAL; 2292 goto error; 2293 } 2294 2295 /* Save token. */ 2296 tokens[n_tokens] = token; 2297 n_tokens++; 2298 } 2299 2300 /* Handle empty lines. */ 2301 if (!n_tokens) 2302 continue; 2303 2304 /* struct block. */ 2305 if (block_mask & (1 << STRUCT_BLOCK)) { 2306 status = struct_block_parse(&struct_spec, 2307 &block_mask, 2308 tokens, 2309 n_tokens, 2310 n_lines, 2311 err_line, 2312 err_msg); 2313 if (status) 2314 goto error; 2315 2316 if (block_mask & (1 << STRUCT_BLOCK)) 2317 continue; 2318 2319 /* End of block. */ 2320 status = rte_swx_pipeline_struct_type_register(p, 2321 struct_spec.name, 2322 struct_spec.fields, 2323 struct_spec.n_fields, 2324 struct_spec.varbit); 2325 if (status) { 2326 if (err_line) 2327 *err_line = n_lines; 2328 if (err_msg) 2329 *err_msg = "Struct registration error."; 2330 goto error; 2331 } 2332 2333 struct_spec_free(&struct_spec); 2334 2335 continue; 2336 } 2337 2338 /* action block. */ 2339 if (block_mask & (1 << ACTION_BLOCK)) { 2340 status = action_block_parse(&action_spec, 2341 &block_mask, 2342 tokens, 2343 n_tokens, 2344 n_lines, 2345 err_line, 2346 err_msg); 2347 if (status) 2348 goto error; 2349 2350 if (block_mask & (1 << ACTION_BLOCK)) 2351 continue; 2352 2353 /* End of block. */ 2354 status = rte_swx_pipeline_action_config(p, 2355 action_spec.name, 2356 action_spec.args_struct_type_name, 2357 action_spec.instructions, 2358 action_spec.n_instructions); 2359 if (status) { 2360 if (err_line) 2361 *err_line = n_lines; 2362 if (err_msg) 2363 *err_msg = "Action config error."; 2364 goto error; 2365 } 2366 2367 action_spec_free(&action_spec); 2368 2369 continue; 2370 } 2371 2372 /* table block. */ 2373 if (block_mask & (1 << TABLE_BLOCK)) { 2374 status = table_block_parse(&table_spec, 2375 &block_mask, 2376 tokens, 2377 n_tokens, 2378 n_lines, 2379 err_line, 2380 err_msg); 2381 if (status) 2382 goto error; 2383 2384 if (block_mask & (1 << TABLE_BLOCK)) 2385 continue; 2386 2387 /* End of block. */ 2388 status = rte_swx_pipeline_table_config(p, 2389 table_spec.name, 2390 &table_spec.params, 2391 table_spec.recommended_table_type_name, 2392 table_spec.args, 2393 table_spec.size); 2394 if (status) { 2395 if (err_line) 2396 *err_line = n_lines; 2397 if (err_msg) 2398 *err_msg = "Table configuration error."; 2399 goto error; 2400 } 2401 2402 table_spec_free(&table_spec); 2403 2404 continue; 2405 } 2406 2407 /* selector block. */ 2408 if (block_mask & (1 << SELECTOR_BLOCK)) { 2409 status = selector_block_parse(&selector_spec, 2410 &block_mask, 2411 tokens, 2412 n_tokens, 2413 n_lines, 2414 err_line, 2415 err_msg); 2416 if (status) 2417 goto error; 2418 2419 if (block_mask & (1 << SELECTOR_BLOCK)) 2420 continue; 2421 2422 /* End of block. */ 2423 status = rte_swx_pipeline_selector_config(p, 2424 selector_spec.name, 2425 &selector_spec.params); 2426 if (status) { 2427 if (err_line) 2428 *err_line = n_lines; 2429 if (err_msg) 2430 *err_msg = "Selector configuration error."; 2431 goto error; 2432 } 2433 2434 selector_spec_free(&selector_spec); 2435 2436 continue; 2437 } 2438 2439 /* learner block. */ 2440 if (block_mask & (1 << LEARNER_BLOCK)) { 2441 status = learner_block_parse(&learner_spec, 2442 &block_mask, 2443 tokens, 2444 n_tokens, 2445 n_lines, 2446 err_line, 2447 err_msg); 2448 if (status) 2449 goto error; 2450 2451 if (block_mask & (1 << LEARNER_BLOCK)) 2452 continue; 2453 2454 /* End of block. */ 2455 status = rte_swx_pipeline_learner_config(p, 2456 learner_spec.name, 2457 &learner_spec.params, 2458 learner_spec.size, 2459 learner_spec.timeout, 2460 learner_spec.n_timeouts); 2461 if (status) { 2462 if (err_line) 2463 *err_line = n_lines; 2464 if (err_msg) 2465 *err_msg = "Learner table configuration error."; 2466 goto error; 2467 } 2468 2469 learner_spec_free(&learner_spec); 2470 2471 continue; 2472 } 2473 2474 /* apply block. */ 2475 if (block_mask & (1 << APPLY_BLOCK)) { 2476 status = apply_block_parse(&apply_spec, 2477 &block_mask, 2478 tokens, 2479 n_tokens, 2480 n_lines, 2481 err_line, 2482 err_msg); 2483 if (status) 2484 goto error; 2485 2486 if (block_mask & (1 << APPLY_BLOCK)) 2487 continue; 2488 2489 /* End of block. */ 2490 status = rte_swx_pipeline_instructions_config(p, 2491 apply_spec.instructions, 2492 apply_spec.n_instructions); 2493 if (status) { 2494 if (err_line) 2495 *err_line = n_lines; 2496 if (err_msg) 2497 *err_msg = "Pipeline instructions err."; 2498 goto error; 2499 } 2500 2501 apply_spec_free(&apply_spec); 2502 2503 continue; 2504 } 2505 2506 /* extobj. */ 2507 if (!strcmp(tokens[0], "extobj")) { 2508 status = extobj_statement_parse(&extobj_spec, 2509 tokens, 2510 n_tokens, 2511 n_lines, 2512 err_line, 2513 err_msg); 2514 if (status) 2515 goto error; 2516 2517 status = rte_swx_pipeline_extern_object_config(p, 2518 extobj_spec.name, 2519 extobj_spec.extern_type_name, 2520 extobj_spec.pragma); 2521 if (status) { 2522 if (err_line) 2523 *err_line = n_lines; 2524 if (err_msg) 2525 *err_msg = "Extern object config err."; 2526 goto error; 2527 } 2528 2529 extobj_spec_free(&extobj_spec); 2530 2531 continue; 2532 } 2533 2534 /* struct. */ 2535 if (!strcmp(tokens[0], "struct")) { 2536 status = struct_statement_parse(&struct_spec, 2537 &block_mask, 2538 tokens, 2539 n_tokens, 2540 n_lines, 2541 err_line, 2542 err_msg); 2543 if (status) 2544 goto error; 2545 2546 continue; 2547 } 2548 2549 /* header. */ 2550 if (!strcmp(tokens[0], "header")) { 2551 status = header_statement_parse(&header_spec, 2552 tokens, 2553 n_tokens, 2554 n_lines, 2555 err_line, 2556 err_msg); 2557 if (status) 2558 goto error; 2559 2560 status = rte_swx_pipeline_packet_header_register(p, 2561 header_spec.name, 2562 header_spec.struct_type_name); 2563 if (status) { 2564 if (err_line) 2565 *err_line = n_lines; 2566 if (err_msg) 2567 *err_msg = "Header registration error."; 2568 goto error; 2569 } 2570 2571 header_spec_free(&header_spec); 2572 2573 continue; 2574 } 2575 2576 /* metadata. */ 2577 if (!strcmp(tokens[0], "metadata")) { 2578 status = metadata_statement_parse(&metadata_spec, 2579 tokens, 2580 n_tokens, 2581 n_lines, 2582 err_line, 2583 err_msg); 2584 if (status) 2585 goto error; 2586 2587 status = rte_swx_pipeline_packet_metadata_register(p, 2588 metadata_spec.struct_type_name); 2589 if (status) { 2590 if (err_line) 2591 *err_line = n_lines; 2592 if (err_msg) 2593 *err_msg = "Meta-data reg err."; 2594 goto error; 2595 } 2596 2597 metadata_spec_free(&metadata_spec); 2598 2599 continue; 2600 } 2601 2602 /* action. */ 2603 if (!strcmp(tokens[0], "action")) { 2604 status = action_statement_parse(&action_spec, 2605 &block_mask, 2606 tokens, 2607 n_tokens, 2608 n_lines, 2609 err_line, 2610 err_msg); 2611 if (status) 2612 goto error; 2613 2614 continue; 2615 } 2616 2617 /* table. */ 2618 if (!strcmp(tokens[0], "table")) { 2619 status = table_statement_parse(&table_spec, 2620 &block_mask, 2621 tokens, 2622 n_tokens, 2623 n_lines, 2624 err_line, 2625 err_msg); 2626 if (status) 2627 goto error; 2628 2629 continue; 2630 } 2631 2632 /* selector. */ 2633 if (!strcmp(tokens[0], "selector")) { 2634 status = selector_statement_parse(&selector_spec, 2635 &block_mask, 2636 tokens, 2637 n_tokens, 2638 n_lines, 2639 err_line, 2640 err_msg); 2641 if (status) 2642 goto error; 2643 2644 continue; 2645 } 2646 2647 /* learner. */ 2648 if (!strcmp(tokens[0], "learner")) { 2649 status = learner_statement_parse(&learner_spec, 2650 &block_mask, 2651 tokens, 2652 n_tokens, 2653 n_lines, 2654 err_line, 2655 err_msg); 2656 if (status) 2657 goto error; 2658 2659 continue; 2660 } 2661 2662 /* regarray. */ 2663 if (!strcmp(tokens[0], "regarray")) { 2664 status = regarray_statement_parse(®array_spec, 2665 tokens, 2666 n_tokens, 2667 n_lines, 2668 err_line, 2669 err_msg); 2670 if (status) 2671 goto error; 2672 2673 status = rte_swx_pipeline_regarray_config(p, 2674 regarray_spec.name, 2675 regarray_spec.size, 2676 regarray_spec.init_val); 2677 if (status) { 2678 if (err_line) 2679 *err_line = n_lines; 2680 if (err_msg) 2681 *err_msg = "Register array configuration error."; 2682 goto error; 2683 } 2684 2685 regarray_spec_free(®array_spec); 2686 2687 continue; 2688 } 2689 2690 /* metarray. */ 2691 if (!strcmp(tokens[0], "metarray")) { 2692 status = metarray_statement_parse(&metarray_spec, 2693 tokens, 2694 n_tokens, 2695 n_lines, 2696 err_line, 2697 err_msg); 2698 if (status) 2699 goto error; 2700 2701 status = rte_swx_pipeline_metarray_config(p, 2702 metarray_spec.name, 2703 metarray_spec.size); 2704 if (status) { 2705 if (err_line) 2706 *err_line = n_lines; 2707 if (err_msg) 2708 *err_msg = "Meter array configuration error."; 2709 goto error; 2710 } 2711 2712 metarray_spec_free(&metarray_spec); 2713 2714 continue; 2715 } 2716 2717 /* apply. */ 2718 if (!strcmp(tokens[0], "apply")) { 2719 status = apply_statement_parse(&block_mask, 2720 tokens, 2721 n_tokens, 2722 n_lines, 2723 err_line, 2724 err_msg); 2725 if (status) 2726 goto error; 2727 2728 continue; 2729 } 2730 2731 /* Anything else. */ 2732 if (err_line) 2733 *err_line = n_lines; 2734 if (err_msg) 2735 *err_msg = "Unknown statement."; 2736 status = -EINVAL; 2737 goto error; 2738 } 2739 2740 /* Handle unfinished block. */ 2741 if (block_mask) { 2742 if (err_line) 2743 *err_line = n_lines; 2744 if (err_msg) 2745 *err_msg = "Missing }."; 2746 status = -EINVAL; 2747 goto error; 2748 } 2749 2750 /* Pipeline build. */ 2751 status = rte_swx_pipeline_build(p); 2752 if (status) { 2753 if (err_line) 2754 *err_line = n_lines; 2755 if (err_msg) 2756 *err_msg = "Pipeline build error."; 2757 goto error; 2758 } 2759 2760 return 0; 2761 2762 error: 2763 extobj_spec_free(&extobj_spec); 2764 struct_spec_free(&struct_spec); 2765 header_spec_free(&header_spec); 2766 metadata_spec_free(&metadata_spec); 2767 action_spec_free(&action_spec); 2768 table_spec_free(&table_spec); 2769 selector_spec_free(&selector_spec); 2770 learner_spec_free(&learner_spec); 2771 regarray_spec_free(®array_spec); 2772 metarray_spec_free(&metarray_spec); 2773 apply_spec_free(&apply_spec); 2774 return status; 2775 } 2776