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 * apply. 2054 * 2055 */ 2056 static void 2057 apply_spec_free(struct apply_spec *s) 2058 { 2059 uint32_t i; 2060 2061 if (!s) 2062 return; 2063 2064 for (i = 0; i < s->n_instructions; i++) { 2065 uintptr_t instr = (uintptr_t)s->instructions[i]; 2066 2067 free((void *)instr); 2068 } 2069 2070 free(s->instructions); 2071 s->instructions = NULL; 2072 2073 s->n_instructions = 0; 2074 } 2075 2076 static int 2077 apply_statement_parse(uint32_t *block_mask, 2078 char **tokens, 2079 uint32_t n_tokens, 2080 uint32_t n_lines, 2081 uint32_t *err_line, 2082 const char **err_msg) 2083 { 2084 /* Check format. */ 2085 if ((n_tokens != 2) || strcmp(tokens[1], "{")) { 2086 if (err_line) 2087 *err_line = n_lines; 2088 if (err_msg) 2089 *err_msg = "Invalid apply statement."; 2090 return -EINVAL; 2091 } 2092 2093 /* block_mask. */ 2094 *block_mask |= 1 << APPLY_BLOCK; 2095 2096 return 0; 2097 } 2098 2099 static int 2100 apply_block_parse(struct apply_spec *s, 2101 uint32_t *block_mask, 2102 char **tokens, 2103 uint32_t n_tokens, 2104 uint32_t n_lines, 2105 uint32_t *err_line, 2106 const char **err_msg) 2107 { 2108 char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr; 2109 const char **new_instructions; 2110 uint32_t i; 2111 2112 /* Handle end of block. */ 2113 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { 2114 *block_mask &= ~(1 << APPLY_BLOCK); 2115 return 0; 2116 } 2117 2118 /* spec. */ 2119 buffer[0] = 0; 2120 for (i = 0; i < n_tokens; i++) { 2121 if (i) 2122 strcat(buffer, " "); 2123 strcat(buffer, tokens[i]); 2124 } 2125 2126 instr = strdup(buffer); 2127 if (!instr) { 2128 if (err_line) 2129 *err_line = n_lines; 2130 if (err_msg) 2131 *err_msg = "Memory allocation failed."; 2132 return -ENOMEM; 2133 } 2134 2135 new_instructions = realloc(s->instructions, 2136 (s->n_instructions + 1) * sizeof(char *)); 2137 if (!new_instructions) { 2138 free(instr); 2139 2140 if (err_line) 2141 *err_line = n_lines; 2142 if (err_msg) 2143 *err_msg = "Memory allocation failed."; 2144 return -ENOMEM; 2145 } 2146 2147 s->instructions = new_instructions; 2148 s->instructions[s->n_instructions] = instr; 2149 s->n_instructions++; 2150 2151 return 0; 2152 } 2153 2154 /* 2155 * Pipeline. 2156 */ 2157 void 2158 pipeline_spec_free(struct pipeline_spec *s) 2159 { 2160 if (!s) 2161 return; 2162 2163 free(s->extobjs); 2164 free(s->structs); 2165 free(s->headers); 2166 free(s->metadata); 2167 free(s->actions); 2168 free(s->tables); 2169 free(s->selectors); 2170 free(s->learners); 2171 free(s->regarrays); 2172 free(s->metarrays); 2173 free(s->apply); 2174 2175 memset(s, 0, sizeof(struct pipeline_spec)); 2176 } 2177 2178 static const char * 2179 match_type_string_get(enum rte_swx_table_match_type match_type) 2180 { 2181 switch (match_type) { 2182 case RTE_SWX_TABLE_MATCH_WILDCARD: return "RTE_SWX_TABLE_MATCH_WILDCARD"; 2183 case RTE_SWX_TABLE_MATCH_LPM: return "RTE_SWX_TABLE_MATCH_LPM"; 2184 case RTE_SWX_TABLE_MATCH_EXACT: return "RTE_SWX_TABLE_MATCH_EXACT"; 2185 default: return "RTE_SWX_TABLE_MATCH_UNKNOWN"; 2186 } 2187 } 2188 2189 void 2190 pipeline_spec_codegen(FILE *f, 2191 struct pipeline_spec *s) 2192 { 2193 uint32_t i; 2194 2195 /* Check the input arguments. */ 2196 if (!f || !s) 2197 return; 2198 2199 /* extobj. */ 2200 fprintf(f, "static struct extobj_spec extobjs[] = {\n"); 2201 2202 for (i = 0; i < s->n_extobjs; i++) { 2203 struct extobj_spec *extobj_spec = &s->extobjs[i]; 2204 2205 fprintf(f, "\t[%d] = {\n", i); 2206 fprintf(f, "\t\t.name = \"%s\",\n", extobj_spec->name); 2207 fprintf(f, "\t\t.extern_type_name = \"%s\",\n", extobj_spec->extern_type_name); 2208 if (extobj_spec->pragma) 2209 fprintf(f, "\t\t.pragma = \"%s\",\n", extobj_spec->pragma); 2210 else 2211 fprintf(f, "\t\t.pragma = NULL,\n"); 2212 fprintf(f, "\t},\n"); 2213 } 2214 2215 fprintf(f, "};\n\n"); 2216 2217 /* regarray. */ 2218 fprintf(f, "static struct regarray_spec regarrays[] = {\n"); 2219 2220 for (i = 0; i < s->n_regarrays; i++) { 2221 struct regarray_spec *regarray_spec = &s->regarrays[i]; 2222 2223 fprintf(f, "\t[%d] = {\n", i); 2224 fprintf(f, "\t\t.name = \"%s\",\n", regarray_spec->name); 2225 fprintf(f, "\t\t.init_val = %" PRIu64 ",\n", regarray_spec->init_val); 2226 fprintf(f, "\t\t.size = %u,\n", regarray_spec->size); 2227 fprintf(f, "\t},\n"); 2228 } 2229 2230 fprintf(f, "};\n\n"); 2231 2232 /* metarray. */ 2233 fprintf(f, "static struct metarray_spec metarrays[] = {\n"); 2234 2235 for (i = 0; i < s->n_metarrays; i++) { 2236 struct metarray_spec *metarray_spec = &s->metarrays[i]; 2237 2238 fprintf(f, "\t[%d] = {\n", i); 2239 fprintf(f, "\t\t.name = \"%s\",\n", metarray_spec->name); 2240 fprintf(f, "\t\t.size = %u,\n", metarray_spec->size); 2241 fprintf(f, "\t},\n"); 2242 } 2243 2244 fprintf(f, "};\n\n"); 2245 2246 /* struct. */ 2247 for (i = 0; i < s->n_structs; i++) { 2248 struct struct_spec *struct_spec = &s->structs[i]; 2249 uint32_t j; 2250 2251 fprintf(f, "static struct rte_swx_field_params struct_%s_fields[] = {\n", 2252 struct_spec->name); 2253 2254 for (j = 0; j < struct_spec->n_fields; j++) { 2255 struct rte_swx_field_params *field = &struct_spec->fields[j]; 2256 2257 fprintf(f, "\t[%d] = {\n", j); 2258 fprintf(f, "\t\t.name = \"%s\",\n", field->name); 2259 fprintf(f, "\t\t.n_bits = %u,\n", field->n_bits); 2260 fprintf(f, "\t},\n"); 2261 } 2262 2263 fprintf(f, "};\n\n"); 2264 } 2265 2266 fprintf(f, "static struct struct_spec structs[] = {\n"); 2267 2268 for (i = 0; i < s->n_structs; i++) { 2269 struct struct_spec *struct_spec = &s->structs[i]; 2270 2271 fprintf(f, "\t[%d] = {\n", i); 2272 fprintf(f, "\t\t.name = \"%s\",\n", struct_spec->name); 2273 fprintf(f, "\t\t.fields = struct_%s_fields,\n", struct_spec->name); 2274 fprintf(f, "\t\t.n_fields = " 2275 "sizeof(struct_%s_fields) / sizeof(struct_%s_fields[0]),\n", 2276 struct_spec->name, 2277 struct_spec->name); 2278 fprintf(f, "\t\t.varbit = %d,\n", struct_spec->varbit); 2279 fprintf(f, "\t},\n"); 2280 } 2281 2282 fprintf(f, "};\n\n"); 2283 2284 /* header. */ 2285 fprintf(f, "static struct header_spec headers[] = {\n"); 2286 2287 for (i = 0; i < s->n_headers; i++) { 2288 struct header_spec *header_spec = &s->headers[i]; 2289 2290 fprintf(f, "\t[%d] = {\n", i); 2291 fprintf(f, "\t\t.name = \"%s\",\n", header_spec->name); 2292 fprintf(f, "\t\t.struct_type_name = \"%s\",\n", header_spec->struct_type_name); 2293 fprintf(f, "\t},\n"); 2294 } 2295 2296 fprintf(f, "};\n\n"); 2297 2298 /* metadata. */ 2299 fprintf(f, "static struct metadata_spec metadata[] = {\n"); 2300 2301 for (i = 0; i < s->n_metadata; i++) { 2302 struct metadata_spec *metadata_spec = &s->metadata[i]; 2303 2304 fprintf(f, "\t[%d] = {\n", i); 2305 fprintf(f, "\t\t.struct_type_name = \"%s\",\n", metadata_spec->struct_type_name); 2306 fprintf(f, "\t},\n"); 2307 2308 } 2309 2310 fprintf(f, "};\n\n"); 2311 2312 /* action. */ 2313 for (i = 0; i < s->n_actions; i++) { 2314 struct action_spec *action_spec = &s->actions[i]; 2315 uint32_t j; 2316 2317 fprintf(f, "static const char *action_%s_initial_instructions[] = {\n", 2318 action_spec->name); 2319 2320 for (j = 0; j < action_spec->n_instructions; j++) { 2321 const char *instr = action_spec->instructions[j]; 2322 2323 fprintf(f, "\t[%d] = \"%s\",\n", j, instr); 2324 } 2325 2326 fprintf(f, "};\n\n"); 2327 } 2328 2329 fprintf(f, "static struct action_spec actions[] = {\n"); 2330 2331 for (i = 0; i < s->n_actions; i++) { 2332 struct action_spec *action_spec = &s->actions[i]; 2333 2334 fprintf(f, "\t[%d] = {\n", i); 2335 fprintf(f, "\t\t.name = \"%s\",\n", action_spec->name); 2336 2337 if (action_spec->args_struct_type_name) 2338 fprintf(f, "\t\t.args_struct_type_name = \"%s\",\n", 2339 action_spec->args_struct_type_name); 2340 else 2341 fprintf(f, "\t\t.args_struct_type_name = NULL,\n"); 2342 2343 fprintf(f, "\t\t.instructions = action_%s_initial_instructions,\n", 2344 action_spec->name); 2345 fprintf(f, "\t\t.n_instructions = " 2346 "sizeof(action_%s_initial_instructions) / " 2347 "sizeof(action_%s_initial_instructions[0]),\n", 2348 action_spec->name, 2349 action_spec->name); 2350 fprintf(f, "\t},\n"); 2351 } 2352 2353 fprintf(f, "};\n\n"); 2354 2355 /* table. */ 2356 for (i = 0; i < s->n_tables; i++) { 2357 struct table_spec *table_spec = &s->tables[i]; 2358 uint32_t j; 2359 2360 /* fields. */ 2361 if (table_spec->params.fields && table_spec->params.n_fields) { 2362 fprintf(f, "static struct rte_swx_match_field_params " 2363 "table_%s_fields[] = {\n", 2364 table_spec->name); 2365 2366 for (j = 0; j < table_spec->params.n_fields; j++) { 2367 struct rte_swx_match_field_params *field = 2368 &table_spec->params.fields[j]; 2369 2370 fprintf(f, "\t[%d] = {\n", j); 2371 fprintf(f, "\t\t.name = \"%s\",\n", field->name); 2372 fprintf(f, "\t\t.match_type = %s,\n", 2373 match_type_string_get(field->match_type)); 2374 fprintf(f, "\t},\n"); 2375 } 2376 2377 fprintf(f, "};\n\n"); 2378 } 2379 2380 /* action_names. */ 2381 if (table_spec->params.action_names && table_spec->params.n_actions) { 2382 fprintf(f, "static const char *table_%s_action_names[] = {\n", 2383 table_spec->name); 2384 2385 for (j = 0; j < table_spec->params.n_actions; j++) { 2386 const char *action_name = table_spec->params.action_names[j]; 2387 2388 fprintf(f, "\t[%d] = \"%s\",\n", j, action_name); 2389 } 2390 2391 fprintf(f, "};\n\n"); 2392 } 2393 2394 /* action_is_for_table_entries. */ 2395 if (table_spec->params.action_is_for_table_entries && 2396 table_spec->params.n_actions) { 2397 fprintf(f, "static int table_%s_action_is_for_table_entries[] = {\n", 2398 table_spec->name); 2399 2400 for (j = 0; j < table_spec->params.n_actions; j++) { 2401 int value = table_spec->params.action_is_for_table_entries[j]; 2402 2403 fprintf(f, "\t[%d] = %d,\n", j, value); 2404 } 2405 2406 fprintf(f, "};\n\n"); 2407 } 2408 2409 /* action_is_for_default_entry. */ 2410 if (table_spec->params.action_is_for_default_entry && 2411 table_spec->params.n_actions) { 2412 fprintf(f, "static int table_%s_action_is_for_default_entry[] = {\n", 2413 table_spec->name); 2414 2415 for (j = 0; j < table_spec->params.n_actions; j++) { 2416 int value = table_spec->params.action_is_for_default_entry[j]; 2417 2418 fprintf(f, "\t[%d] = %d,\n", j, value); 2419 } 2420 2421 fprintf(f, "};\n\n"); 2422 } 2423 } 2424 2425 fprintf(f, "static struct table_spec tables[] = {\n"); 2426 2427 for (i = 0; i < s->n_tables; i++) { 2428 struct table_spec *table_spec = &s->tables[i]; 2429 2430 fprintf(f, "\t[%d] = {\n", i); 2431 fprintf(f, "\t\t.name = \"%s\",\n", table_spec->name); 2432 2433 fprintf(f, "\t\t.params = {\n"); 2434 2435 if (table_spec->params.fields && table_spec->params.n_fields) { 2436 fprintf(f, "\t\t\t.fields = table_%s_fields,\n", table_spec->name); 2437 fprintf(f, "\t\t\t.n_fields = " 2438 "sizeof(table_%s_fields) / sizeof(table_%s_fields[0]),\n", 2439 table_spec->name, 2440 table_spec->name); 2441 } else { 2442 fprintf(f, "\t\t\t.fields = NULL,\n"); 2443 fprintf(f, "\t\t\t.n_fields = 0,\n"); 2444 } 2445 2446 if (table_spec->params.action_names && table_spec->params.n_actions) 2447 fprintf(f, "\t\t\t.action_names = table_%s_action_names,\n", 2448 table_spec->name); 2449 else 2450 fprintf(f, "\t\t\t.action_names = NULL,\n"); 2451 2452 if (table_spec->params.action_is_for_table_entries && table_spec->params.n_actions) 2453 fprintf(f, "\t\t\t.action_is_for_table_entries = " 2454 "table_%s_action_is_for_table_entries,\n", 2455 table_spec->name); 2456 else 2457 fprintf(f, "\t\t\t.action_is_for_table_entries = NULL,\n"); 2458 2459 if (table_spec->params.action_is_for_default_entry && table_spec->params.n_actions) 2460 fprintf(f, "\t\t\t.action_is_for_default_entry = " 2461 "table_%s_action_is_for_default_entry,\n", 2462 table_spec->name); 2463 else 2464 fprintf(f, "\t\t\t.action_is_for_default_entry = NULL,\n"); 2465 2466 if (table_spec->params.n_actions) 2467 fprintf(f, "\t\t\t.n_actions = sizeof(table_%s_action_names) / " 2468 "sizeof(table_%s_action_names[0]),\n", 2469 table_spec->name, 2470 table_spec->name); 2471 else 2472 fprintf(f, "\t\t\t.n_actions = 0,\n"); 2473 2474 if (table_spec->params.default_action_name) 2475 fprintf(f, "\t\t\t.default_action_name = \"%s\",\n", 2476 table_spec->params.default_action_name); 2477 else 2478 fprintf(f, "\t\t\t.default_action_name = NULL,\n"); 2479 2480 if (table_spec->params.default_action_args) 2481 fprintf(f, "\t\t\t.default_action_args = \"%s\",\n", 2482 table_spec->params.default_action_args); 2483 else 2484 fprintf(f, "\t\t\t.default_action_args = NULL,\n"); 2485 2486 fprintf(f, "\t\t\t.default_action_is_const = %d,\n", 2487 table_spec->params.default_action_is_const); 2488 2489 if (table_spec->params.hash_func_name) 2490 fprintf(f, "\t\t\t.hash_func_name = \"%s\",\n", 2491 table_spec->params.hash_func_name); 2492 else 2493 fprintf(f, "\t\t\t.hash_func_name = NULL,\n"); 2494 2495 fprintf(f, "\t\t},\n"); 2496 2497 if (table_spec->recommended_table_type_name) 2498 fprintf(f, "\t\t.recommended_table_type_name = \"%s\",\n", 2499 table_spec->recommended_table_type_name); 2500 else 2501 fprintf(f, "\t\t.recommended_table_type_name = NULL,\n"); 2502 2503 if (table_spec->args) 2504 fprintf(f, "\t\t.args = \"%s\",\n", table_spec->args); 2505 else 2506 fprintf(f, "\t\t.args = NULL,\n"); 2507 2508 fprintf(f, "\t\t.size = %u,\n", table_spec->size); 2509 2510 fprintf(f, "\t},\n"); 2511 } 2512 2513 fprintf(f, "};\n\n"); 2514 2515 /* selector. */ 2516 for (i = 0; i < s->n_selectors; i++) { 2517 struct selector_spec *selector_spec = &s->selectors[i]; 2518 uint32_t j; 2519 2520 if (selector_spec->params.selector_field_names && 2521 selector_spec->params.n_selector_fields) { 2522 fprintf(f, "static const char *selector_%s_field_names[] = {\n", 2523 selector_spec->name); 2524 2525 for (j = 0; j < selector_spec->params.n_selector_fields; j++) { 2526 const char *field_name = 2527 selector_spec->params.selector_field_names[j]; 2528 2529 fprintf(f, "\t[%d] = \"%s\",\n", j, field_name); 2530 } 2531 2532 fprintf(f, "};\n\n"); 2533 } 2534 } 2535 2536 fprintf(f, "static struct selector_spec selectors[] = {\n"); 2537 2538 for (i = 0; i < s->n_selectors; i++) { 2539 struct selector_spec *selector_spec = &s->selectors[i]; 2540 2541 fprintf(f, "\t[%d] = {\n", i); 2542 2543 fprintf(f, "\t\t.name = \"%s\",\n", selector_spec->name); 2544 fprintf(f, "\t\t.params = {\n"); 2545 2546 if (selector_spec->params.group_id_field_name) 2547 fprintf(f, "\t\t\t.group_id_field_name = \"%s\",\n", 2548 selector_spec->params.group_id_field_name); 2549 else 2550 fprintf(f, "\t\t\t.group_id_field_name = NULL,\n"); 2551 2552 if (selector_spec->params.selector_field_names && 2553 selector_spec->params.n_selector_fields) { 2554 fprintf(f, "\t\t\t.selector_field_names = selector_%s_field_names,\n", 2555 selector_spec->name); 2556 fprintf(f, "\t\t\t.n_selector_fields = " 2557 "sizeof(selector_%s_field_names) / sizeof(selector_%s_field_names[0]),\n", 2558 selector_spec->name, 2559 selector_spec->name); 2560 } else { 2561 fprintf(f, "\t\t\t.selector_field_names = NULL,\n"); 2562 fprintf(f, "\t\t\t.n_selector_fields = 0,\n"); 2563 } 2564 2565 if (selector_spec->params.member_id_field_name) 2566 fprintf(f, "\t\t\t.member_id_field_name = \"%s\",\n", 2567 selector_spec->params.member_id_field_name); 2568 else 2569 fprintf(f, "\t\t\t.member_id_field_name = NULL,\n"); 2570 2571 fprintf(f, "\t\t\t.n_groups_max = %u,\n", selector_spec->params.n_groups_max); 2572 2573 fprintf(f, "\t\t\t.n_members_per_group_max = %u,\n", 2574 selector_spec->params.n_members_per_group_max); 2575 2576 fprintf(f, "\t\t},\n"); 2577 fprintf(f, "\t},\n"); 2578 } 2579 2580 fprintf(f, "};\n\n"); 2581 2582 /* learner. */ 2583 for (i = 0; i < s->n_learners; i++) { 2584 struct learner_spec *learner_spec = &s->learners[i]; 2585 uint32_t j; 2586 2587 /* field_names. */ 2588 if (learner_spec->params.field_names && learner_spec->params.n_fields) { 2589 fprintf(f, "static const char *learner_%s_field_names[] = {\n", 2590 learner_spec->name); 2591 2592 for (j = 0; j < learner_spec->params.n_fields; j++) { 2593 const char *field_name = learner_spec->params.field_names[j]; 2594 2595 fprintf(f, "\t[%d] = \"%s\",\n", j, field_name); 2596 } 2597 2598 fprintf(f, "};\n\n"); 2599 } 2600 2601 /* action_names. */ 2602 if (learner_spec->params.action_names && learner_spec->params.n_actions) { 2603 fprintf(f, "static const char *learner_%s_action_names[] = {\n", 2604 learner_spec->name); 2605 2606 for (j = 0; j < learner_spec->params.n_actions; j++) { 2607 const char *action_name = learner_spec->params.action_names[j]; 2608 2609 fprintf(f, "\t[%d] = \"%s\",\n", j, action_name); 2610 } 2611 2612 fprintf(f, "};\n\n"); 2613 } 2614 2615 /* action_is_for_table_entries. */ 2616 if (learner_spec->params.action_is_for_table_entries && 2617 learner_spec->params.n_actions) { 2618 fprintf(f, "static int learner_%s_action_is_for_table_entries[] = {\n", 2619 learner_spec->name); 2620 2621 for (j = 0; j < learner_spec->params.n_actions; j++) { 2622 int value = learner_spec->params.action_is_for_table_entries[j]; 2623 2624 fprintf(f, "\t[%d] = %d,\n", j, value); 2625 } 2626 2627 fprintf(f, "};\n\n"); 2628 } 2629 2630 /* action_is_for_default_entry. */ 2631 if (learner_spec->params.action_is_for_default_entry && 2632 learner_spec->params.n_actions) { 2633 fprintf(f, "static int learner_%s_action_is_for_default_entry[] = {\n", 2634 learner_spec->name); 2635 2636 for (j = 0; j < learner_spec->params.n_actions; j++) { 2637 int value = learner_spec->params.action_is_for_default_entry[j]; 2638 2639 fprintf(f, "\t[%d] = %d,\n", j, value); 2640 } 2641 2642 fprintf(f, "};\n\n"); 2643 } 2644 2645 /* timeout. */ 2646 if (learner_spec->timeout && learner_spec->n_timeouts) { 2647 fprintf(f, "static uint32_t learner_%s_timeout[] = {\n", 2648 learner_spec->name); 2649 2650 for (j = 0; j < learner_spec->n_timeouts; j++) { 2651 uint32_t value = learner_spec->timeout[j]; 2652 2653 fprintf(f, "\t[%d] = %u,\n", j, value); 2654 } 2655 2656 fprintf(f, "};\n\n"); 2657 } 2658 } 2659 2660 fprintf(f, "static struct learner_spec learners[] = {\n"); 2661 2662 for (i = 0; i < s->n_learners; i++) { 2663 struct learner_spec *learner_spec = &s->learners[i]; 2664 2665 fprintf(f, "\t[%d] = {\n", i); 2666 fprintf(f, "\t\t.name = \"%s\",\n", learner_spec->name); 2667 2668 fprintf(f, "\t\t.params = {\n"); 2669 2670 if (learner_spec->params.field_names && learner_spec->params.n_fields) { 2671 fprintf(f, "\t\t\t.field_names = learner_%s_field_names,\n", 2672 learner_spec->name); 2673 fprintf(f, "\t\t\t.n_fields = " 2674 "sizeof(learner_%s_field_names) / " 2675 "sizeof(learner_%s_field_names[0]),\n", 2676 learner_spec->name, 2677 learner_spec->name); 2678 } else { 2679 fprintf(f, "\t\t\t.field_names = NULL,\n"); 2680 fprintf(f, "\t\t\t.n_fields = 0,\n"); 2681 } 2682 2683 if (learner_spec->params.action_names && learner_spec->params.n_actions) 2684 fprintf(f, "\t\t\t.action_names = learner_%s_action_names,\n", 2685 learner_spec->name); 2686 else 2687 fprintf(f, "\t\t\t.action_names = NULL,\n"); 2688 2689 if (learner_spec->params.action_is_for_table_entries && 2690 learner_spec->params.n_actions) 2691 fprintf(f, "\t\t\t.action_is_for_table_entries = " 2692 "learner_%s_action_is_for_table_entries,\n", 2693 learner_spec->name); 2694 else 2695 fprintf(f, "\t\t\t.action_is_for_table_entries = NULL,\n"); 2696 2697 if (learner_spec->params.action_is_for_default_entry && 2698 learner_spec->params.n_actions) 2699 fprintf(f, "\t\t\t.action_is_for_default_entry = " 2700 "learner_%s_action_is_for_default_entry,\n", 2701 learner_spec->name); 2702 else 2703 fprintf(f, "\t\t\t.action_is_for_default_entry = NULL,\n"); 2704 2705 if (learner_spec->params.action_names && learner_spec->params.n_actions) 2706 fprintf(f, "\t\t\t.n_actions = " 2707 "sizeof(learner_%s_action_names) / sizeof(learner_%s_action_names[0]),\n", 2708 learner_spec->name, 2709 learner_spec->name); 2710 else 2711 fprintf(f, "\t\t\t.n_actions = NULL,\n"); 2712 2713 if (learner_spec->params.default_action_name) 2714 fprintf(f, "\t\t\t.default_action_name = \"%s\",\n", 2715 learner_spec->params.default_action_name); 2716 else 2717 fprintf(f, "\t\t\t.default_action_name = NULL,\n"); 2718 2719 if (learner_spec->params.default_action_args) 2720 fprintf(f, "\t\t\t.default_action_args = \"%s\",\n", 2721 learner_spec->params.default_action_args); 2722 else 2723 fprintf(f, "\t\t\t.default_action_args = NULL,\n"); 2724 2725 fprintf(f, "\t\t\t.default_action_is_const = %d,\n", 2726 learner_spec->params.default_action_is_const); 2727 2728 if (learner_spec->params.hash_func_name) 2729 fprintf(f, "\t\t\t.hash_func_name = \"%s\",\n", 2730 learner_spec->params.hash_func_name); 2731 else 2732 fprintf(f, "\t\t\t.hash_func_name = NULL,\n"); 2733 2734 fprintf(f, "\t\t},\n"); 2735 2736 fprintf(f, "\t\t.size = %u,\n", learner_spec->size); 2737 2738 if (learner_spec->timeout && learner_spec->n_timeouts) { 2739 fprintf(f, "\t\t.timeout = learner_%s_timeout,\n", learner_spec->name); 2740 fprintf(f, "\t\t\t.n_timeouts = " 2741 "sizeof(learner_%s_timeout) / sizeof(learner_%s_timeout[0]),\n", 2742 learner_spec->name, 2743 learner_spec->name); 2744 } else { 2745 fprintf(f, "\t\t.timeout = NULL,\n"); 2746 fprintf(f, "\t\t\t.n_timeouts = 0,\n"); 2747 } 2748 2749 fprintf(f, "\t},\n"); 2750 } 2751 2752 fprintf(f, "};\n\n"); 2753 2754 /* apply. */ 2755 for (i = 0; i < s->n_apply; i++) { 2756 struct apply_spec *apply_spec = &s->apply[i]; 2757 uint32_t j; 2758 2759 fprintf(f, "static const char *apply%u_initial_instructions[] = {\n", i); 2760 2761 for (j = 0; j < apply_spec->n_instructions; j++) { 2762 const char *instr = apply_spec->instructions[j]; 2763 2764 fprintf(f, "\t[%d] = \"%s\",\n", j, instr); 2765 } 2766 2767 fprintf(f, "};\n\n"); 2768 } 2769 2770 fprintf(f, "static struct apply_spec apply[] = {\n"); 2771 2772 for (i = 0; i < s->n_apply; i++) { 2773 fprintf(f, "\t[%d] = {\n", i); 2774 fprintf(f, "\t.instructions = apply%u_initial_instructions,\n", i); 2775 fprintf(f, "\t.n_instructions = " 2776 "sizeof(apply%u_initial_instructions) / " 2777 "sizeof(apply%u_initial_instructions[0]),\n", 2778 i, 2779 i); 2780 fprintf(f, "\t},\n"); 2781 } 2782 2783 fprintf(f, "};\n\n"); 2784 2785 /* pipeline. */ 2786 fprintf(f, "struct pipeline_spec pipeline_spec = {\n"); 2787 fprintf(f, "\t.extobjs = extobjs,\n"); 2788 fprintf(f, "\t.structs = structs,\n"); 2789 fprintf(f, "\t.headers = headers,\n"); 2790 fprintf(f, "\t.metadata = metadata,\n"); 2791 fprintf(f, "\t.actions = actions,\n"); 2792 fprintf(f, "\t.tables = tables,\n"); 2793 fprintf(f, "\t.selectors = selectors,\n"); 2794 fprintf(f, "\t.learners = learners,\n"); 2795 fprintf(f, "\t.regarrays = regarrays,\n"); 2796 fprintf(f, "\t.metarrays = metarrays,\n"); 2797 fprintf(f, "\t.apply = apply,\n"); 2798 fprintf(f, "\t.n_extobjs = sizeof(extobjs) / sizeof(extobjs[0]),\n"); 2799 fprintf(f, "\t.n_structs = sizeof(structs) / sizeof(structs[0]),\n"); 2800 fprintf(f, "\t.n_headers = sizeof(headers) / sizeof(headers[0]),\n"); 2801 fprintf(f, "\t.n_metadata = sizeof(metadata) / sizeof(metadata[0]),\n"); 2802 fprintf(f, "\t.n_actions = sizeof(actions) / sizeof(actions[0]),\n"); 2803 fprintf(f, "\t.n_tables = sizeof(tables) / sizeof(tables[0]),\n"); 2804 fprintf(f, "\t.n_selectors = sizeof(selectors) / sizeof(selectors[0]),\n"); 2805 fprintf(f, "\t.n_learners = sizeof(learners) / sizeof(learners[0]),\n"); 2806 fprintf(f, "\t.n_regarrays = sizeof(regarrays) / sizeof(regarrays[0]),\n"); 2807 fprintf(f, "\t.n_metarrays = sizeof(metarrays) / sizeof(metarrays[0]),\n"); 2808 fprintf(f, "\t.n_apply = sizeof(apply) / sizeof(apply[0]),\n"); 2809 fprintf(f, "};\n"); 2810 } 2811 2812 struct pipeline_spec * 2813 pipeline_spec_parse(FILE *spec, 2814 uint32_t *err_line, 2815 const char **err_msg) 2816 { 2817 struct extobj_spec extobj_spec = {0}; 2818 struct struct_spec struct_spec = {0}; 2819 struct header_spec header_spec = {0}; 2820 struct metadata_spec metadata_spec = {0}; 2821 struct action_spec action_spec = {0}; 2822 struct table_spec table_spec = {0}; 2823 struct selector_spec selector_spec = {0}; 2824 struct learner_spec learner_spec = {0}; 2825 struct regarray_spec regarray_spec = {0}; 2826 struct metarray_spec metarray_spec = {0}; 2827 struct apply_spec apply_spec = {0}; 2828 struct pipeline_spec *s = NULL; 2829 uint32_t n_lines = 0; 2830 uint32_t block_mask = 0; 2831 int status = 0; 2832 2833 /* Check the input arguments. */ 2834 if (!spec) { 2835 if (err_line) 2836 *err_line = n_lines; 2837 if (err_msg) 2838 *err_msg = "Invalid input argument."; 2839 status = -EINVAL; 2840 goto error; 2841 } 2842 2843 /* Memory allocation. */ 2844 s = calloc(sizeof(struct pipeline_spec), 1); 2845 if (!s) { 2846 if (err_line) 2847 *err_line = n_lines; 2848 if (err_msg) 2849 *err_msg = "Memory allocation failed."; 2850 status = -ENOMEM; 2851 goto error; 2852 } 2853 2854 for (n_lines = 1; ; n_lines++) { 2855 char line[MAX_LINE_LENGTH]; 2856 char *tokens[MAX_TOKENS], *ptr = line; 2857 uint32_t n_tokens = 0; 2858 2859 /* Read next line. */ 2860 if (!fgets(line, sizeof(line), spec)) 2861 break; 2862 2863 /* Parse the line into tokens. */ 2864 for ( ; ; ) { 2865 char *token; 2866 2867 /* Get token. */ 2868 token = strtok_r(ptr, " \f\n\r\t\v", &ptr); 2869 if (!token) 2870 break; 2871 2872 /* Handle comments. */ 2873 if ((token[0] == '#') || 2874 (token[0] == ';') || 2875 ((token[0] == '/') && (token[1] == '/'))) { 2876 break; 2877 } 2878 2879 /* Handle excessively long lines. */ 2880 if (n_tokens >= RTE_DIM(tokens)) { 2881 if (err_line) 2882 *err_line = n_lines; 2883 if (err_msg) 2884 *err_msg = "Too many tokens."; 2885 status = -EINVAL; 2886 goto error; 2887 } 2888 2889 /* Handle excessively long tokens. */ 2890 if (strnlen(token, RTE_SWX_NAME_SIZE) >= 2891 RTE_SWX_NAME_SIZE) { 2892 if (err_line) 2893 *err_line = n_lines; 2894 if (err_msg) 2895 *err_msg = "Token too big."; 2896 status = -EINVAL; 2897 goto error; 2898 } 2899 2900 /* Save token. */ 2901 tokens[n_tokens] = token; 2902 n_tokens++; 2903 } 2904 2905 /* Handle empty lines. */ 2906 if (!n_tokens) 2907 continue; 2908 2909 /* struct block. */ 2910 if (block_mask & (1 << STRUCT_BLOCK)) { 2911 struct struct_spec *new_structs; 2912 2913 status = struct_block_parse(&struct_spec, 2914 &block_mask, 2915 tokens, 2916 n_tokens, 2917 n_lines, 2918 err_line, 2919 err_msg); 2920 if (status) 2921 goto error; 2922 2923 if (block_mask & (1 << STRUCT_BLOCK)) 2924 continue; 2925 2926 /* End of block. */ 2927 new_structs = realloc(s->structs, 2928 (s->n_structs + 1) * sizeof(struct struct_spec)); 2929 if (!new_structs) { 2930 if (err_line) 2931 *err_line = n_lines; 2932 if (err_msg) 2933 *err_msg = "Memory allocation failed."; 2934 status = -ENOMEM; 2935 goto error; 2936 } 2937 2938 s->structs = new_structs; 2939 memcpy(&s->structs[s->n_structs], &struct_spec, sizeof(struct struct_spec)); 2940 s->n_structs++; 2941 memset(&struct_spec, 0, sizeof(struct struct_spec)); 2942 2943 continue; 2944 } 2945 2946 /* action block. */ 2947 if (block_mask & (1 << ACTION_BLOCK)) { 2948 struct action_spec *new_actions; 2949 2950 status = action_block_parse(&action_spec, 2951 &block_mask, 2952 tokens, 2953 n_tokens, 2954 n_lines, 2955 err_line, 2956 err_msg); 2957 if (status) 2958 goto error; 2959 2960 if (block_mask & (1 << ACTION_BLOCK)) 2961 continue; 2962 2963 /* End of block. */ 2964 new_actions = realloc(s->actions, 2965 (s->n_actions + 1) * sizeof(struct action_spec)); 2966 if (!new_actions) { 2967 if (err_line) 2968 *err_line = n_lines; 2969 if (err_msg) 2970 *err_msg = "Memory allocation failed."; 2971 status = -ENOMEM; 2972 goto error; 2973 } 2974 2975 s->actions = new_actions; 2976 memcpy(&s->actions[s->n_actions], &action_spec, sizeof(struct action_spec)); 2977 s->n_actions++; 2978 memset(&action_spec, 0, sizeof(struct action_spec)); 2979 2980 continue; 2981 } 2982 2983 /* table block. */ 2984 if (block_mask & (1 << TABLE_BLOCK)) { 2985 struct table_spec *new_tables; 2986 2987 status = table_block_parse(&table_spec, 2988 &block_mask, 2989 tokens, 2990 n_tokens, 2991 n_lines, 2992 err_line, 2993 err_msg); 2994 if (status) 2995 goto error; 2996 2997 if (block_mask & (1 << TABLE_BLOCK)) 2998 continue; 2999 3000 /* End of block. */ 3001 new_tables = realloc(s->tables, 3002 (s->n_tables + 1) * sizeof(struct table_spec)); 3003 if (!new_tables) { 3004 if (err_line) 3005 *err_line = n_lines; 3006 if (err_msg) 3007 *err_msg = "Memory allocation failed."; 3008 status = -ENOMEM; 3009 goto error; 3010 } 3011 3012 s->tables = new_tables; 3013 memcpy(&s->tables[s->n_tables], &table_spec, sizeof(struct table_spec)); 3014 s->n_tables++; 3015 memset(&table_spec, 0, sizeof(struct table_spec)); 3016 3017 continue; 3018 } 3019 3020 /* selector block. */ 3021 if (block_mask & (1 << SELECTOR_BLOCK)) { 3022 struct selector_spec *new_selectors; 3023 3024 status = selector_block_parse(&selector_spec, 3025 &block_mask, 3026 tokens, 3027 n_tokens, 3028 n_lines, 3029 err_line, 3030 err_msg); 3031 if (status) 3032 goto error; 3033 3034 if (block_mask & (1 << SELECTOR_BLOCK)) 3035 continue; 3036 3037 /* End of block. */ 3038 new_selectors = realloc(s->selectors, 3039 (s->n_selectors + 1) * sizeof(struct selector_spec)); 3040 if (!new_selectors) { 3041 if (err_line) 3042 *err_line = n_lines; 3043 if (err_msg) 3044 *err_msg = "Memory allocation failed."; 3045 status = -ENOMEM; 3046 goto error; 3047 } 3048 3049 s->selectors = new_selectors; 3050 memcpy(&s->selectors[s->n_selectors], 3051 &selector_spec, 3052 sizeof(struct selector_spec)); 3053 s->n_selectors++; 3054 memset(&selector_spec, 0, sizeof(struct selector_spec)); 3055 3056 continue; 3057 } 3058 3059 /* learner block. */ 3060 if (block_mask & (1 << LEARNER_BLOCK)) { 3061 struct learner_spec *new_learners; 3062 3063 status = learner_block_parse(&learner_spec, 3064 &block_mask, 3065 tokens, 3066 n_tokens, 3067 n_lines, 3068 err_line, 3069 err_msg); 3070 if (status) 3071 goto error; 3072 3073 if (block_mask & (1 << LEARNER_BLOCK)) 3074 continue; 3075 3076 /* End of block. */ 3077 new_learners = realloc(s->learners, 3078 (s->n_learners + 1) * sizeof(struct learner_spec)); 3079 if (!new_learners) { 3080 if (err_line) 3081 *err_line = n_lines; 3082 if (err_msg) 3083 *err_msg = "Memory allocation failed."; 3084 status = -ENOMEM; 3085 goto error; 3086 } 3087 3088 s->learners = new_learners; 3089 memcpy(&s->learners[s->n_learners], 3090 &learner_spec, 3091 sizeof(struct learner_spec)); 3092 s->n_learners++; 3093 memset(&learner_spec, 0, sizeof(struct learner_spec)); 3094 3095 continue; 3096 } 3097 3098 /* apply block. */ 3099 if (block_mask & (1 << APPLY_BLOCK)) { 3100 struct apply_spec *new_apply; 3101 3102 status = apply_block_parse(&apply_spec, 3103 &block_mask, 3104 tokens, 3105 n_tokens, 3106 n_lines, 3107 err_line, 3108 err_msg); 3109 if (status) 3110 goto error; 3111 3112 if (block_mask & (1 << APPLY_BLOCK)) 3113 continue; 3114 3115 /* End of block. */ 3116 new_apply = realloc(s->apply, (s->n_apply + 1) * sizeof(struct apply_spec)); 3117 if (!new_apply) { 3118 if (err_line) 3119 *err_line = n_lines; 3120 if (err_msg) 3121 *err_msg = "Memory allocation failed."; 3122 status = -ENOMEM; 3123 goto error; 3124 } 3125 3126 s->apply = new_apply; 3127 memcpy(&s->apply[s->n_apply], &apply_spec, sizeof(struct apply_spec)); 3128 s->n_apply++; 3129 memset(&apply_spec, 0, sizeof(struct apply_spec)); 3130 3131 continue; 3132 } 3133 3134 /* extobj. */ 3135 if (!strcmp(tokens[0], "extobj")) { 3136 struct extobj_spec *new_extobjs; 3137 3138 status = extobj_statement_parse(&extobj_spec, 3139 tokens, 3140 n_tokens, 3141 n_lines, 3142 err_line, 3143 err_msg); 3144 if (status) 3145 goto error; 3146 3147 new_extobjs = realloc(s->extobjs, 3148 (s->n_extobjs + 1) * sizeof(struct extobj_spec)); 3149 if (!new_extobjs) { 3150 if (err_line) 3151 *err_line = n_lines; 3152 if (err_msg) 3153 *err_msg = "Memory allocation failed."; 3154 status = -ENOMEM; 3155 goto error; 3156 } 3157 3158 s->extobjs = new_extobjs; 3159 memcpy(&s->extobjs[s->n_extobjs], &extobj_spec, sizeof(struct extobj_spec)); 3160 s->n_extobjs++; 3161 memset(&extobj_spec, 0, sizeof(struct extobj_spec)); 3162 3163 continue; 3164 } 3165 3166 /* struct. */ 3167 if (!strcmp(tokens[0], "struct")) { 3168 status = struct_statement_parse(&struct_spec, 3169 &block_mask, 3170 tokens, 3171 n_tokens, 3172 n_lines, 3173 err_line, 3174 err_msg); 3175 if (status) 3176 goto error; 3177 3178 continue; 3179 } 3180 3181 /* header. */ 3182 if (!strcmp(tokens[0], "header")) { 3183 struct header_spec *new_headers; 3184 3185 status = header_statement_parse(&header_spec, 3186 tokens, 3187 n_tokens, 3188 n_lines, 3189 err_line, 3190 err_msg); 3191 if (status) 3192 goto error; 3193 3194 new_headers = realloc(s->headers, 3195 (s->n_headers + 1) * sizeof(struct header_spec)); 3196 if (!new_headers) { 3197 if (err_line) 3198 *err_line = n_lines; 3199 if (err_msg) 3200 *err_msg = "Memory allocation failed."; 3201 status = -ENOMEM; 3202 goto error; 3203 } 3204 3205 s->headers = new_headers; 3206 memcpy(&s->headers[s->n_headers], &header_spec, sizeof(struct header_spec)); 3207 s->n_headers++; 3208 memset(&header_spec, 0, sizeof(struct header_spec)); 3209 3210 continue; 3211 } 3212 3213 /* metadata. */ 3214 if (!strcmp(tokens[0], "metadata")) { 3215 struct metadata_spec *new_metadata; 3216 3217 status = metadata_statement_parse(&metadata_spec, 3218 tokens, 3219 n_tokens, 3220 n_lines, 3221 err_line, 3222 err_msg); 3223 if (status) 3224 goto error; 3225 3226 new_metadata = realloc(s->metadata, 3227 (s->n_metadata + 1) * sizeof(struct metadata_spec)); 3228 if (!new_metadata) { 3229 if (err_line) 3230 *err_line = n_lines; 3231 if (err_msg) 3232 *err_msg = "Memory allocation failed."; 3233 status = -ENOMEM; 3234 goto error; 3235 } 3236 3237 s->metadata = new_metadata; 3238 memcpy(&s->metadata[s->n_metadata], 3239 &metadata_spec, 3240 sizeof(struct metadata_spec)); 3241 s->n_metadata++; 3242 memset(&metadata_spec, 0, sizeof(struct metadata_spec)); 3243 3244 continue; 3245 } 3246 3247 /* action. */ 3248 if (!strcmp(tokens[0], "action")) { 3249 status = action_statement_parse(&action_spec, 3250 &block_mask, 3251 tokens, 3252 n_tokens, 3253 n_lines, 3254 err_line, 3255 err_msg); 3256 if (status) 3257 goto error; 3258 3259 continue; 3260 } 3261 3262 /* table. */ 3263 if (!strcmp(tokens[0], "table")) { 3264 status = table_statement_parse(&table_spec, 3265 &block_mask, 3266 tokens, 3267 n_tokens, 3268 n_lines, 3269 err_line, 3270 err_msg); 3271 if (status) 3272 goto error; 3273 3274 continue; 3275 } 3276 3277 /* selector. */ 3278 if (!strcmp(tokens[0], "selector")) { 3279 status = selector_statement_parse(&selector_spec, 3280 &block_mask, 3281 tokens, 3282 n_tokens, 3283 n_lines, 3284 err_line, 3285 err_msg); 3286 if (status) 3287 goto error; 3288 3289 continue; 3290 } 3291 3292 /* learner. */ 3293 if (!strcmp(tokens[0], "learner")) { 3294 status = learner_statement_parse(&learner_spec, 3295 &block_mask, 3296 tokens, 3297 n_tokens, 3298 n_lines, 3299 err_line, 3300 err_msg); 3301 if (status) 3302 goto error; 3303 3304 continue; 3305 } 3306 3307 /* regarray. */ 3308 if (!strcmp(tokens[0], "regarray")) { 3309 struct regarray_spec *new_regarrays; 3310 3311 status = regarray_statement_parse(®array_spec, 3312 tokens, 3313 n_tokens, 3314 n_lines, 3315 err_line, 3316 err_msg); 3317 if (status) 3318 goto error; 3319 3320 new_regarrays = realloc(s->regarrays, 3321 (s->n_regarrays + 1) * sizeof(struct regarray_spec)); 3322 if (!new_regarrays) { 3323 if (err_line) 3324 *err_line = n_lines; 3325 if (err_msg) 3326 *err_msg = "Memory allocation failed."; 3327 status = -ENOMEM; 3328 goto error; 3329 } 3330 3331 s->regarrays = new_regarrays; 3332 memcpy(&s->regarrays[s->n_regarrays], 3333 ®array_spec, 3334 sizeof(struct regarray_spec)); 3335 s->n_regarrays++; 3336 memset(®array_spec, 0, sizeof(struct regarray_spec)); 3337 3338 continue; 3339 } 3340 3341 /* metarray. */ 3342 if (!strcmp(tokens[0], "metarray")) { 3343 struct metarray_spec *new_metarrays; 3344 3345 status = metarray_statement_parse(&metarray_spec, 3346 tokens, 3347 n_tokens, 3348 n_lines, 3349 err_line, 3350 err_msg); 3351 if (status) 3352 goto error; 3353 3354 new_metarrays = realloc(s->metarrays, 3355 (s->n_metarrays + 1) * sizeof(struct metarray_spec)); 3356 if (!new_metarrays) { 3357 if (err_line) 3358 *err_line = n_lines; 3359 if (err_msg) 3360 *err_msg = "Memory allocation failed."; 3361 status = -ENOMEM; 3362 goto error; 3363 } 3364 3365 s->metarrays = new_metarrays; 3366 memcpy(&s->metarrays[s->n_metarrays], 3367 &metarray_spec, 3368 sizeof(struct metarray_spec)); 3369 s->n_metarrays++; 3370 memset(&metarray_spec, 0, sizeof(struct metarray_spec)); 3371 3372 continue; 3373 } 3374 3375 /* apply. */ 3376 if (!strcmp(tokens[0], "apply")) { 3377 status = apply_statement_parse(&block_mask, 3378 tokens, 3379 n_tokens, 3380 n_lines, 3381 err_line, 3382 err_msg); 3383 if (status) 3384 goto error; 3385 3386 continue; 3387 } 3388 3389 /* Anything else. */ 3390 if (err_line) 3391 *err_line = n_lines; 3392 if (err_msg) 3393 *err_msg = "Unknown statement."; 3394 status = -EINVAL; 3395 goto error; 3396 } 3397 3398 /* Handle unfinished block. */ 3399 if (block_mask) { 3400 if (err_line) 3401 *err_line = n_lines; 3402 if (err_msg) 3403 *err_msg = "Missing }."; 3404 status = -EINVAL; 3405 goto error; 3406 } 3407 3408 return s; 3409 3410 error: 3411 extobj_spec_free(&extobj_spec); 3412 struct_spec_free(&struct_spec); 3413 header_spec_free(&header_spec); 3414 metadata_spec_free(&metadata_spec); 3415 action_spec_free(&action_spec); 3416 table_spec_free(&table_spec); 3417 selector_spec_free(&selector_spec); 3418 learner_spec_free(&learner_spec); 3419 regarray_spec_free(®array_spec); 3420 metarray_spec_free(&metarray_spec); 3421 apply_spec_free(&apply_spec); 3422 pipeline_spec_free(s); 3423 3424 return NULL; 3425 } 3426 3427 int 3428 pipeline_spec_configure(struct rte_swx_pipeline *p, 3429 struct pipeline_spec *s, 3430 const char **err_msg) 3431 { 3432 uint32_t i; 3433 int status = 0; 3434 3435 /* extobj. */ 3436 for (i = 0; i < s->n_extobjs; i++) { 3437 struct extobj_spec *extobj_spec = &s->extobjs[i]; 3438 3439 status = rte_swx_pipeline_extern_object_config(p, 3440 extobj_spec->name, 3441 extobj_spec->extern_type_name, 3442 extobj_spec->pragma); 3443 if (status) { 3444 if (err_msg) 3445 *err_msg = "Extern object configuration error."; 3446 return status; 3447 } 3448 } 3449 3450 /* regarray. */ 3451 for (i = 0; i < s->n_regarrays; i++) { 3452 struct regarray_spec *regarray_spec = &s->regarrays[i]; 3453 3454 status = rte_swx_pipeline_regarray_config(p, 3455 regarray_spec->name, 3456 regarray_spec->size, 3457 regarray_spec->init_val); 3458 if (status) { 3459 if (err_msg) 3460 *err_msg = "Register array configuration error."; 3461 return status; 3462 } 3463 } 3464 3465 /* metarray. */ 3466 for (i = 0; i < s->n_metarrays; i++) { 3467 struct metarray_spec *metarray_spec = &s->metarrays[i]; 3468 3469 status = rte_swx_pipeline_metarray_config(p, 3470 metarray_spec->name, 3471 metarray_spec->size); 3472 if (status) { 3473 if (err_msg) 3474 *err_msg = "Meter array configuration error."; 3475 return status; 3476 } 3477 } 3478 3479 /* struct. */ 3480 for (i = 0; i < s->n_structs; i++) { 3481 struct struct_spec *struct_spec = &s->structs[i]; 3482 3483 status = rte_swx_pipeline_struct_type_register(p, 3484 struct_spec->name, 3485 struct_spec->fields, 3486 struct_spec->n_fields, 3487 struct_spec->varbit); 3488 if (status) { 3489 if (err_msg) 3490 *err_msg = "Struct type registration error."; 3491 return status; 3492 } 3493 } 3494 3495 /* header. */ 3496 for (i = 0; i < s->n_headers; i++) { 3497 struct header_spec *header_spec = &s->headers[i]; 3498 3499 status = rte_swx_pipeline_packet_header_register(p, 3500 header_spec->name, 3501 header_spec->struct_type_name); 3502 if (status) { 3503 if (err_msg) 3504 *err_msg = "Header configuration error."; 3505 return status; 3506 } 3507 } 3508 3509 /* metadata. */ 3510 for (i = 0; i < s->n_metadata; i++) { 3511 struct metadata_spec *metadata_spec = &s->metadata[i]; 3512 3513 status = rte_swx_pipeline_packet_metadata_register(p, 3514 metadata_spec->struct_type_name); 3515 if (status) { 3516 if (err_msg) 3517 *err_msg = "Meta-data registration error."; 3518 return status; 3519 } 3520 } 3521 3522 /* action. */ 3523 for (i = 0; i < s->n_actions; i++) { 3524 struct action_spec *action_spec = &s->actions[i]; 3525 3526 status = rte_swx_pipeline_action_config(p, 3527 action_spec->name, 3528 action_spec->args_struct_type_name, 3529 action_spec->instructions, 3530 action_spec->n_instructions); 3531 if (status) { 3532 if (err_msg) 3533 *err_msg = "Action configuration error."; 3534 return status; 3535 } 3536 } 3537 3538 /* table. */ 3539 for (i = 0; i < s->n_tables; i++) { 3540 struct table_spec *table_spec = &s->tables[i]; 3541 3542 status = rte_swx_pipeline_table_config(p, 3543 table_spec->name, 3544 &table_spec->params, 3545 table_spec->recommended_table_type_name, 3546 table_spec->args, 3547 table_spec->size); 3548 if (status) { 3549 if (err_msg) 3550 *err_msg = "Table configuration error."; 3551 return status; 3552 } 3553 } 3554 3555 /* selector. */ 3556 for (i = 0; i < s->n_selectors; i++) { 3557 struct selector_spec *selector_spec = &s->selectors[i]; 3558 3559 status = rte_swx_pipeline_selector_config(p, 3560 selector_spec->name, 3561 &selector_spec->params); 3562 if (status) { 3563 if (err_msg) 3564 *err_msg = "Selector table configuration error."; 3565 return status; 3566 } 3567 } 3568 3569 /* learner. */ 3570 for (i = 0; i < s->n_learners; i++) { 3571 struct learner_spec *learner_spec = &s->learners[i]; 3572 3573 status = rte_swx_pipeline_learner_config(p, 3574 learner_spec->name, 3575 &learner_spec->params, 3576 learner_spec->size, 3577 learner_spec->timeout, 3578 learner_spec->n_timeouts); 3579 if (status) { 3580 if (err_msg) 3581 *err_msg = "Learner table configuration error."; 3582 return status; 3583 } 3584 } 3585 3586 /* apply. */ 3587 for (i = 0; i < s->n_apply; i++) { 3588 struct apply_spec *apply_spec = &s->apply[i]; 3589 3590 status = rte_swx_pipeline_instructions_config(p, 3591 apply_spec->instructions, 3592 apply_spec->n_instructions); 3593 if (status) { 3594 if (err_msg) 3595 *err_msg = "Pipeline instructions configuration error."; 3596 return status; 3597 } 3598 } 3599 3600 return 0; 3601 } 3602 3603 static void 3604 port_in_params_free(void *params, const char *port_type) 3605 { 3606 uintptr_t dev_name; 3607 3608 if (!params || !port_type) 3609 return; 3610 3611 if (!strcmp(port_type, "ethdev")) { 3612 struct rte_swx_port_ethdev_reader_params *p = params; 3613 3614 dev_name = (uintptr_t)p->dev_name; 3615 } else if (!strcmp(port_type, "ring")) { 3616 struct rte_swx_port_ring_reader_params *p = params; 3617 3618 dev_name = (uintptr_t)p->name; 3619 } else if (!strcmp(port_type, "source")) { 3620 struct rte_swx_port_source_params *p = params; 3621 3622 dev_name = (uintptr_t)p->file_name; 3623 } else 3624 dev_name = (uintptr_t)NULL; 3625 3626 free((void *)dev_name); 3627 free(params); 3628 } 3629 3630 static void 3631 port_out_params_free(void *params, const char *port_type) 3632 { 3633 uintptr_t dev_name; 3634 3635 if (!params || !port_type) 3636 return; 3637 3638 if (!strcmp(port_type, "ethdev")) { 3639 struct rte_swx_port_ethdev_writer_params *p = params; 3640 3641 dev_name = (uintptr_t)p->dev_name; 3642 } else if (!strcmp(port_type, "ring")) { 3643 struct rte_swx_port_ring_writer_params *p = params; 3644 3645 dev_name = (uintptr_t)p->name; 3646 } else if (!strcmp(port_type, "sink")) { 3647 struct rte_swx_port_sink_params *p = params; 3648 3649 dev_name = (uintptr_t)p->file_name; 3650 } else 3651 dev_name = (uintptr_t)NULL; 3652 3653 free((void *)dev_name); 3654 free(params); 3655 } 3656 3657 void 3658 pipeline_iospec_free(struct pipeline_iospec *s) 3659 { 3660 uint32_t i; 3661 3662 if (!s) 3663 return; 3664 3665 /* Input ports. */ 3666 for (i = 0; i < s->n_ports_in; i++) { 3667 uintptr_t name = (uintptr_t)s->port_in_type[i]; 3668 3669 port_in_params_free(s->port_in_params[i], s->port_in_type[i]); 3670 free((void *)name); 3671 } 3672 3673 free(s->port_in_type); 3674 free(s->port_in_params); 3675 3676 /* Output ports. */ 3677 for (i = 0; i < s->n_ports_out; i++) { 3678 uintptr_t name = (uintptr_t)s->port_out_type[i]; 3679 3680 port_out_params_free(s->port_out_params[i], s->port_out_type[i]); 3681 free((void *)name); 3682 } 3683 3684 free(s->port_out_type); 3685 free(s->port_out_params); 3686 3687 free(s); 3688 } 3689 3690 static int 3691 mirroring_parse(struct rte_swx_pipeline_mirroring_params *p, 3692 char **tokens, 3693 uint32_t n_tokens, 3694 const char **err_msg) 3695 { 3696 char *token; 3697 3698 if ((n_tokens != 4) || strcmp(tokens[0], "slots") || strcmp(tokens[2], "sessions")) { 3699 if (err_msg) 3700 *err_msg = "Invalid statement."; 3701 return -EINVAL; 3702 } 3703 3704 /* <n_slots>. */ 3705 token = tokens[1]; 3706 p->n_slots = strtoul(token, &token, 0); 3707 if (token[0]) { 3708 if (err_msg) 3709 *err_msg = "Invalid <n_slots> parameter."; 3710 return -EINVAL; 3711 } 3712 3713 /* <n_sessions>. */ 3714 token = tokens[3]; 3715 p->n_sessions = strtoul(token, &token, 0); 3716 if (token[0]) { 3717 if (err_msg) 3718 *err_msg = "Invalid <n_sessions> parameter."; 3719 return -EINVAL; 3720 } 3721 3722 return 0; 3723 } 3724 3725 static void * 3726 port_in_ethdev_parse(char **tokens, uint32_t n_tokens, const char **err_msg) 3727 { 3728 struct rte_swx_port_ethdev_reader_params *p = NULL; 3729 char *token, *dev_name = NULL; 3730 uint32_t queue_id, burst_size; 3731 3732 if ((n_tokens != 5) || strcmp(tokens[1], "rxq") || strcmp(tokens[3], "bsz")) { 3733 if (err_msg) 3734 *err_msg = "Invalid statement."; 3735 return NULL; 3736 } 3737 3738 /* <queue_id>. */ 3739 token = tokens[2]; 3740 queue_id = strtoul(token, &token, 0); 3741 if (token[0]) { 3742 if (err_msg) 3743 *err_msg = "Invalid <queue_id> parameter."; 3744 return NULL; 3745 } 3746 3747 /* <burst_size>. */ 3748 token = tokens[4]; 3749 burst_size = strtoul(token, &token, 0); 3750 if (token[0]) { 3751 if (err_msg) 3752 *err_msg = "Invalid <burst_size> parameter."; 3753 return NULL; 3754 } 3755 3756 /* Memory allocation. */ 3757 dev_name = strdup(tokens[0]); 3758 p = malloc(sizeof(struct rte_swx_port_ethdev_reader_params)); 3759 if (!dev_name || !p) { 3760 free(dev_name); 3761 free(p); 3762 3763 if (err_msg) 3764 *err_msg = "Memory allocation failed."; 3765 return NULL; 3766 } 3767 3768 /* Initialization. */ 3769 p->dev_name = dev_name; 3770 p->queue_id = queue_id; 3771 p->burst_size = burst_size; 3772 3773 return p; 3774 } 3775 3776 static void * 3777 port_in_ring_parse(char **tokens, uint32_t n_tokens, const char **err_msg) 3778 { 3779 struct rte_swx_port_ring_reader_params *p = NULL; 3780 char *token, *name = NULL; 3781 uint32_t burst_size; 3782 3783 if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) { 3784 if (err_msg) 3785 *err_msg = "Invalid statement."; 3786 return NULL; 3787 } 3788 3789 /* <burst_size>. */ 3790 token = tokens[2]; 3791 burst_size = strtoul(token, &token, 0); 3792 if (token[0]) { 3793 if (err_msg) 3794 *err_msg = "Invalid <burst_size> parameter."; 3795 return NULL; 3796 } 3797 3798 /* Memory allocation. */ 3799 name = strdup(tokens[0]); 3800 p = malloc(sizeof(struct rte_swx_port_ring_reader_params)); 3801 if (!name || !p) { 3802 free(name); 3803 free(p); 3804 3805 if (err_msg) 3806 *err_msg = "Memory allocation failed."; 3807 return NULL; 3808 } 3809 3810 /* Initialization. */ 3811 p->name = name; 3812 p->burst_size = burst_size; 3813 3814 return p; 3815 } 3816 3817 static void * 3818 port_in_source_parse(char **tokens, uint32_t n_tokens, const char **err_msg) 3819 { 3820 struct rte_swx_port_source_params *p = NULL; 3821 struct rte_mempool *pool = NULL; 3822 char *token, *file_name = NULL; 3823 uint32_t n_loops, n_pkts_max; 3824 3825 if ((n_tokens != 8) || 3826 strcmp(tokens[0], "mempool") || 3827 strcmp(tokens[2], "file") || 3828 strcmp(tokens[4], "loop") || 3829 strcmp(tokens[6], "packets")) { 3830 if (err_msg) 3831 *err_msg = "Invalid statement."; 3832 return NULL; 3833 } 3834 3835 /* <mempool_name>. */ 3836 pool = rte_mempool_lookup(tokens[1]); 3837 if (!pool) { 3838 if (err_msg) 3839 *err_msg = "Invalid <mempool_name> parameter."; 3840 return NULL; 3841 } 3842 3843 /* <n_loops>. */ 3844 token = tokens[5]; 3845 n_loops = strtoul(token, &token, 0); 3846 if (token[0]) { 3847 if (err_msg) 3848 *err_msg = "Invalid <n_loops> parameter."; 3849 return NULL; 3850 } 3851 3852 /* <n_pkts_max>. */ 3853 token = tokens[7]; 3854 n_pkts_max = strtoul(token, &token, 0); 3855 if (token[0]) { 3856 if (err_msg) 3857 *err_msg = "Invalid <n_pkts_max> parameter."; 3858 return NULL; 3859 } 3860 3861 /* Memory allocation. */ 3862 file_name = strdup(tokens[3]); 3863 p = malloc(sizeof(struct rte_swx_port_source_params)); 3864 if (!file_name || !p) { 3865 free(file_name); 3866 free(p); 3867 3868 if (err_msg) 3869 *err_msg = "Memory allocation failed."; 3870 return NULL; 3871 } 3872 3873 /* Initialization. */ 3874 p->pool = pool; 3875 p->file_name = file_name; 3876 p->n_loops = n_loops; 3877 p->n_pkts_max = n_pkts_max; 3878 3879 return p; 3880 } 3881 3882 static void * 3883 port_in_fd_parse(char **tokens, 3884 uint32_t n_tokens, 3885 const char **err_msg) 3886 { 3887 struct rte_swx_port_fd_reader_params *p = NULL; 3888 struct rte_mempool *mempool = NULL; 3889 char *token; 3890 uint32_t mtu, burst_size; 3891 int fd; 3892 3893 if ((n_tokens != 7) || 3894 strcmp(tokens[1], "mtu") || 3895 strcmp(tokens[3], "mempool") || 3896 strcmp(tokens[5], "bsz")) { 3897 if (err_msg) 3898 *err_msg = "Invalid statement."; 3899 return NULL; 3900 } 3901 3902 /* <file_descriptor>. */ 3903 token = tokens[0]; 3904 fd = strtol(token, &token, 0); 3905 if (token[0]) { 3906 if (err_msg) 3907 *err_msg = "Invalid <file_descriptor> parameter."; 3908 return NULL; 3909 } 3910 3911 /* <mtu>. */ 3912 token = tokens[2]; 3913 mtu = strtoul(token, &token, 0); 3914 if (token[0]) { 3915 if (err_msg) 3916 *err_msg = "Invalid <mtu> parameter."; 3917 return NULL; 3918 } 3919 3920 /* <mempool_name>. */ 3921 mempool = rte_mempool_lookup(tokens[4]); 3922 if (!mempool) { 3923 if (err_msg) 3924 *err_msg = "Invalid <mempool_name> parameter."; 3925 return NULL; 3926 } 3927 3928 /* <burst_size>. */ 3929 token = tokens[6]; 3930 burst_size = strtoul(token, &token, 0); 3931 if (token[0]) { 3932 if (err_msg) 3933 *err_msg = "Invalid <burst_size> parameter."; 3934 return NULL; 3935 } 3936 3937 /* Memory allocation. */ 3938 p = malloc(sizeof(struct rte_swx_port_fd_reader_params)); 3939 if (!p) { 3940 if (err_msg) 3941 *err_msg = "Memory allocation failed."; 3942 return NULL; 3943 } 3944 3945 /* Initialization. */ 3946 p->fd = fd; 3947 p->mtu = mtu; 3948 p->mempool = mempool; 3949 p->burst_size = burst_size; 3950 3951 return p; 3952 } 3953 3954 static void * 3955 port_out_ethdev_parse(char **tokens, uint32_t n_tokens, const char **err_msg) 3956 { 3957 struct rte_swx_port_ethdev_writer_params *p = NULL; 3958 char *token, *dev_name = NULL; 3959 uint32_t queue_id, burst_size; 3960 3961 if ((n_tokens != 5) || strcmp(tokens[1], "txq") || strcmp(tokens[3], "bsz")) { 3962 if (err_msg) 3963 *err_msg = "Invalid statement."; 3964 return NULL; 3965 } 3966 3967 /* <queue_id>. */ 3968 token = tokens[2]; 3969 queue_id = strtoul(token, &token, 0); 3970 if (token[0]) { 3971 if (err_msg) 3972 *err_msg = "Invalid <queue_id> parameter."; 3973 return NULL; 3974 } 3975 3976 /* <burst_size>. */ 3977 token = tokens[4]; 3978 burst_size = strtoul(token, &token, 0); 3979 if (token[0]) { 3980 if (err_msg) 3981 *err_msg = "Invalid <burst_size> parameter."; 3982 return NULL; 3983 } 3984 3985 /* Memory allocation. */ 3986 dev_name = strdup(tokens[0]); 3987 p = malloc(sizeof(struct rte_swx_port_ethdev_writer_params)); 3988 if (!dev_name || !p) { 3989 free(dev_name); 3990 free(p); 3991 3992 if (err_msg) 3993 *err_msg = "Memory allocation failed."; 3994 return NULL; 3995 } 3996 3997 /* Initialization. */ 3998 p->dev_name = dev_name; 3999 p->queue_id = queue_id; 4000 p->burst_size = burst_size; 4001 4002 return p; 4003 } 4004 4005 static void * 4006 port_out_ring_parse(char **tokens, uint32_t n_tokens, const char **err_msg) 4007 { 4008 struct rte_swx_port_ring_writer_params *p = NULL; 4009 char *token, *name = NULL; 4010 uint32_t burst_size; 4011 4012 if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) { 4013 if (err_msg) 4014 *err_msg = "Invalid statement."; 4015 return NULL; 4016 } 4017 4018 /* <burst_size>. */ 4019 token = tokens[2]; 4020 burst_size = strtoul(token, &token, 0); 4021 if (token[0]) { 4022 if (err_msg) 4023 *err_msg = "Invalid <burst_size> parameter."; 4024 return NULL; 4025 } 4026 4027 /* Memory allocation. */ 4028 name = strdup(tokens[0]); 4029 p = malloc(sizeof(struct rte_swx_port_ring_writer_params)); 4030 if (!name || !p) { 4031 free(name); 4032 free(p); 4033 4034 if (err_msg) 4035 *err_msg = "Memory allocation failed."; 4036 return NULL; 4037 } 4038 4039 /* Initialization. */ 4040 p->name = name; 4041 p->burst_size = burst_size; 4042 4043 return p; 4044 } 4045 4046 static void * 4047 port_out_sink_parse(char **tokens, uint32_t n_tokens, const char **err_msg) 4048 { 4049 struct rte_swx_port_sink_params *p = NULL; 4050 char *file_name = NULL; 4051 int file_name_valid = 0; 4052 4053 if ((n_tokens != 2) || strcmp(tokens[0], "file")) { 4054 if (err_msg) 4055 *err_msg = "Invalid statement."; 4056 return NULL; 4057 } 4058 4059 /* Memory allocation. */ 4060 if (strcmp(tokens[1], "none")) { 4061 file_name_valid = 1; 4062 file_name = strdup(tokens[1]); 4063 } 4064 4065 p = malloc(sizeof(struct rte_swx_port_ring_writer_params)); 4066 if ((file_name_valid && !file_name) || !p) { 4067 free(file_name); 4068 free(p); 4069 4070 if (err_msg) 4071 *err_msg = "Memory allocation failed."; 4072 return NULL; 4073 } 4074 4075 /* Initialization. */ 4076 p->file_name = file_name; 4077 4078 return p; 4079 } 4080 4081 static void * 4082 port_out_fd_parse(char **tokens, 4083 uint32_t n_tokens, 4084 const char **err_msg) 4085 { 4086 struct rte_swx_port_fd_writer_params *p = NULL; 4087 char *token; 4088 uint32_t burst_size; 4089 int fd; 4090 4091 if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) { 4092 if (err_msg) 4093 *err_msg = "Invalid statement."; 4094 return NULL; 4095 } 4096 4097 /* <file_descriptor>. */ 4098 token = tokens[0]; 4099 fd = strtol(token, &token, 0); 4100 if (token[0]) { 4101 if (err_msg) 4102 *err_msg = "Invalid <file_descriptor> parameter."; 4103 return NULL; 4104 } 4105 4106 /* <burst_size>. */ 4107 token = tokens[2]; 4108 burst_size = strtoul(token, &token, 0); 4109 if (token[0]) { 4110 if (err_msg) 4111 *err_msg = "Invalid <burst_size> parameter."; 4112 return NULL; 4113 } 4114 4115 /* Memory allocation. */ 4116 p = malloc(sizeof(struct rte_swx_port_fd_writer_params)); 4117 if (!p) { 4118 if (err_msg) 4119 *err_msg = "Memory allocation failed."; 4120 return NULL; 4121 } 4122 4123 /* Initialization. */ 4124 p->fd = fd; 4125 p->burst_size = burst_size; 4126 4127 return p; 4128 } 4129 4130 struct pipeline_iospec * 4131 pipeline_iospec_parse(FILE *spec, 4132 uint32_t *err_line, 4133 const char **err_msg) 4134 { 4135 struct pipeline_iospec *s = NULL; 4136 uint32_t n_lines = 0; 4137 4138 /* Check the input arguments. */ 4139 if (!spec) { 4140 if (err_line) 4141 *err_line = n_lines; 4142 if (err_msg) 4143 *err_msg = "Invalid input argument."; 4144 goto error; 4145 } 4146 4147 /* Memory allocation. */ 4148 s = calloc(sizeof(struct pipeline_iospec), 1); 4149 if (!s) { 4150 if (err_line) 4151 *err_line = n_lines; 4152 if (err_msg) 4153 *err_msg = "Memory allocation failed."; 4154 goto error; 4155 } 4156 4157 /* Initialize with the default values. */ 4158 s->mirroring_params.n_slots = RTE_SWX_PACKET_MIRRORING_SLOTS_DEFAULT; 4159 s->mirroring_params.n_sessions = RTE_SWX_PACKET_MIRRORING_SESSIONS_DEFAULT; 4160 4161 for (n_lines = 1; ; n_lines++) { 4162 char line[MAX_LINE_LENGTH]; 4163 char *tokens[MAX_TOKENS], *ptr = line; 4164 uint32_t n_tokens = 0; 4165 4166 /* Read next line. */ 4167 if (!fgets(line, sizeof(line), spec)) 4168 break; 4169 4170 /* Parse the line into tokens. */ 4171 for ( ; ; ) { 4172 char *token; 4173 4174 /* Get token. */ 4175 token = strtok_r(ptr, " \f\n\r\t\v", &ptr); 4176 if (!token) 4177 break; 4178 4179 /* Handle comments. */ 4180 if ((token[0] == '#') || 4181 (token[0] == ';') || 4182 ((token[0] == '/') && (token[1] == '/'))) { 4183 break; 4184 } 4185 4186 /* Handle excessively long lines. */ 4187 if (n_tokens >= RTE_DIM(tokens)) { 4188 if (err_line) 4189 *err_line = n_lines; 4190 if (err_msg) 4191 *err_msg = "Too many tokens."; 4192 goto error; 4193 } 4194 4195 /* Handle excessively long tokens. */ 4196 if (strnlen(token, RTE_SWX_NAME_SIZE) >= 4197 RTE_SWX_NAME_SIZE) { 4198 if (err_line) 4199 *err_line = n_lines; 4200 if (err_msg) 4201 *err_msg = "Token too big."; 4202 goto error; 4203 } 4204 4205 /* Save token. */ 4206 tokens[n_tokens] = token; 4207 n_tokens++; 4208 } 4209 4210 /* Handle empty lines. */ 4211 if (!n_tokens) 4212 continue; 4213 4214 /* mirroring. */ 4215 if ((n_tokens >= 1) && !strcmp(tokens[0], "mirroring")) { 4216 int status = 0; 4217 4218 status = mirroring_parse(&s->mirroring_params, 4219 &tokens[1], 4220 n_tokens - 1, 4221 err_msg); 4222 if (status) { 4223 if (err_line) 4224 *err_line = n_lines; 4225 goto error; 4226 } 4227 4228 continue; 4229 } 4230 4231 /* port in. */ 4232 if ((n_tokens >= 4) && !strcmp(tokens[0], "port") && !strcmp(tokens[1], "in")) { 4233 char *token = tokens[2]; 4234 uint32_t *new_id = NULL; 4235 const char **new_type = NULL, *port_type = NULL; 4236 void **new_params = NULL, *p = NULL; 4237 uint32_t port_id; 4238 4239 /* <port_id>. */ 4240 port_id = strtoul(token, &token, 0); 4241 if (token[0]) { 4242 if (err_line) 4243 *err_line = n_lines; 4244 if (err_msg) 4245 *err_msg = "Invalid port ID."; 4246 goto error; 4247 } 4248 4249 /* <port_type>. */ 4250 if (!strcmp(tokens[3], "ethdev")) 4251 p = port_in_ethdev_parse(&tokens[4], n_tokens - 4, err_msg); 4252 else if (!strcmp(tokens[3], "ring")) 4253 p = port_in_ring_parse(&tokens[4], n_tokens - 4, err_msg); 4254 else if (!strcmp(tokens[3], "source")) 4255 p = port_in_source_parse(&tokens[4], n_tokens - 4, err_msg); 4256 else if (!strcmp(tokens[3], "fd")) 4257 p = port_in_fd_parse(&tokens[4], n_tokens - 4, err_msg); 4258 else { 4259 p = NULL; 4260 if (err_msg) 4261 *err_msg = "Invalid port type."; 4262 } 4263 4264 if (!p) { 4265 if (err_line) 4266 *err_line = n_lines; 4267 goto error; 4268 } 4269 4270 /* New port. */ 4271 port_type = strdup(tokens[3]); 4272 new_id = realloc(s->port_in_id, 4273 (s->n_ports_in + 1) * sizeof(uint32_t)); 4274 new_type = realloc(s->port_in_type, 4275 (s->n_ports_in + 1) * sizeof(char *)); 4276 new_params = realloc(s->port_in_params, 4277 (s->n_ports_in + 1) * sizeof(void *)); 4278 if (!port_type || !new_id || !new_type || !new_params) { 4279 uintptr_t pt = (uintptr_t)port_type; 4280 4281 port_in_params_free(p, tokens[3]); 4282 free((void *)pt); 4283 free(new_id); 4284 free(new_type); 4285 free(new_params); 4286 4287 if (err_line) 4288 *err_line = n_lines; 4289 if (err_msg) 4290 *err_msg = "Memory allocation failed."; 4291 goto error; 4292 } 4293 4294 s->port_in_id = new_id; 4295 s->port_in_type = new_type; 4296 s->port_in_params = new_params; 4297 4298 s->port_in_id[s->n_ports_in] = port_id; 4299 s->port_in_type[s->n_ports_in] = port_type; 4300 s->port_in_params[s->n_ports_in] = p; 4301 s->n_ports_in++; 4302 4303 continue; 4304 } 4305 4306 /* port out. */ 4307 if ((n_tokens >= 4) && !strcmp(tokens[0], "port") && !strcmp(tokens[1], "out")) { 4308 char *token = tokens[2]; 4309 uint32_t *new_id = NULL; 4310 const char **new_type = NULL, *port_type = NULL; 4311 void **new_params = NULL, *p = NULL; 4312 uint32_t port_id; 4313 4314 /* <port_id>. */ 4315 port_id = strtoul(token, &token, 0); 4316 if (token[0]) { 4317 if (err_line) 4318 *err_line = n_lines; 4319 if (err_msg) 4320 *err_msg = "Invalid port ID."; 4321 goto error; 4322 } 4323 4324 /* <port_type>. */ 4325 if (!strcmp(tokens[3], "ethdev")) 4326 p = port_out_ethdev_parse(&tokens[4], n_tokens - 4, err_msg); 4327 else if (!strcmp(tokens[3], "ring")) 4328 p = port_out_ring_parse(&tokens[4], n_tokens - 4, err_msg); 4329 else if (!strcmp(tokens[3], "sink")) 4330 p = port_out_sink_parse(&tokens[4], n_tokens - 4, err_msg); 4331 else if (!strcmp(tokens[3], "fd")) 4332 p = port_out_fd_parse(&tokens[4], n_tokens - 4, err_msg); 4333 else { 4334 p = NULL; 4335 if (err_msg) 4336 *err_msg = "Invalid port type."; 4337 } 4338 4339 if (!p) { 4340 if (err_line) 4341 *err_line = n_lines; 4342 goto error; 4343 } 4344 4345 /* New port. */ 4346 port_type = strdup(tokens[3]); 4347 new_id = realloc(s->port_out_id, 4348 (s->n_ports_out + 1) * sizeof(uint32_t)); 4349 new_type = realloc(s->port_out_type, 4350 (s->n_ports_out + 1) * sizeof(char *)); 4351 new_params = realloc(s->port_out_params, 4352 (s->n_ports_out + 1) * sizeof(void *)); 4353 if (!port_type || !new_id || !new_type || !new_params) { 4354 uintptr_t pt = (uintptr_t)port_type; 4355 4356 port_out_params_free(p, tokens[3]); 4357 free((void *)pt); 4358 free(new_id); 4359 free(new_type); 4360 free(new_params); 4361 4362 if (err_line) 4363 *err_line = n_lines; 4364 if (err_msg) 4365 *err_msg = "Memory allocation failed."; 4366 goto error; 4367 } 4368 4369 s->port_out_id = new_id; 4370 s->port_out_type = new_type; 4371 s->port_out_params = new_params; 4372 4373 s->port_out_id[s->n_ports_out] = port_id; 4374 s->port_out_type[s->n_ports_out] = port_type; 4375 s->port_out_params[s->n_ports_out] = p; 4376 s->n_ports_out++; 4377 4378 continue; 4379 } 4380 4381 /* Anything else. */ 4382 if (err_line) 4383 *err_line = n_lines; 4384 if (err_msg) 4385 *err_msg = "Unknown I/O statement."; 4386 goto error; 4387 } 4388 4389 return s; 4390 4391 error: 4392 pipeline_iospec_free(s); 4393 4394 return NULL; 4395 } 4396 4397 int 4398 pipeline_iospec_configure(struct rte_swx_pipeline *p, 4399 struct pipeline_iospec *s, 4400 const char **err_msg) 4401 { 4402 uint32_t i; 4403 int status = 0; 4404 4405 /* Check input arguments. */ 4406 if (!p || !s) { 4407 if (err_msg) 4408 *err_msg = "Invalid input argument"; 4409 return -EINVAL; 4410 } 4411 4412 /* Mirroring. */ 4413 status = rte_swx_pipeline_mirroring_config(p, &s->mirroring_params); 4414 if (status) { 4415 if (err_msg) 4416 *err_msg = "Pipeline mirroring configuration error."; 4417 return status; 4418 } 4419 4420 /* Input ports. */ 4421 for (i = 0; i < s->n_ports_in; i++) { 4422 status = rte_swx_pipeline_port_in_config(p, 4423 i, 4424 s->port_in_type[i], 4425 s->port_in_params[i]); 4426 if (status) { 4427 if (err_msg) 4428 *err_msg = "Pipeline input port configuration error."; 4429 return status; 4430 } 4431 } 4432 4433 /* Output ports. */ 4434 for (i = 0; i < s->n_ports_out; i++) { 4435 status = rte_swx_pipeline_port_out_config(p, 4436 i, 4437 s->port_out_type[i], 4438 s->port_out_params[i]); 4439 if (status) { 4440 if (err_msg) 4441 *err_msg = "Pipeline output port configuration error."; 4442 return status; 4443 } 4444 } 4445 4446 return 0; 4447 } 4448