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