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