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