1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2020 Intel Corporation
10 #include "rte_swx_pipeline.h"
12 #define MAX_LINE_LENGTH RTE_SWX_INSTRUCTION_SIZE
13 #define MAX_TOKENS RTE_SWX_INSTRUCTION_TOKENS_MAX
15 #define STRUCT_BLOCK 0
16 #define ACTION_BLOCK 1
18 #define TABLE_KEY_BLOCK 3
19 #define TABLE_ACTIONS_BLOCK 4
20 #define SELECTOR_BLOCK 5
21 #define SELECTOR_SELECTOR_BLOCK 6
22 #define LEARNER_BLOCK 7
23 #define LEARNER_KEY_BLOCK 8
24 #define LEARNER_ACTIONS_BLOCK 9
25 #define APPLY_BLOCK 10
30 * extobj OBJ_NAME instanceof OBJ_TYPE [ pragma OBJ_CREATE_ARGS ]
34 char *extern_type_name;
39 extobj_spec_free(struct extobj_spec *s)
47 free(s->extern_type_name);
48 s->extern_type_name = NULL;
55 extobj_statement_parse(struct extobj_spec *s,
63 if (((n_tokens != 4) && (n_tokens != 6)) ||
64 ((n_tokens == 4) && strcmp(tokens[2], "instanceof")) ||
65 ((n_tokens == 6) && (strcmp(tokens[2], "instanceof") ||
66 strcmp(tokens[4], "pragma")))) {
70 *err_msg = "Invalid extobj statement.";
75 s->name = strdup(tokens[1]);
76 s->extern_type_name = strdup(tokens[3]);
77 s->pragma = (n_tokens == 6) ? strdup(tokens[5]) : NULL;
80 !s->extern_type_name ||
81 ((n_tokens == 6) && !s->pragma)) {
83 free(s->extern_type_name);
89 *err_msg = "Memory allocation failed.";
99 * struct STRUCT_TYPE_NAME {
100 * bit<SIZE> | varbit<SIZE> FIELD_NAME
106 struct rte_swx_field_params *fields;
112 struct_spec_free(struct struct_spec *s)
122 for (i = 0; i < s->n_fields; i++) {
123 uintptr_t name = (uintptr_t)s->fields[i].name;
137 struct_statement_parse(struct struct_spec *s,
138 uint32_t *block_mask,
143 const char **err_msg)
146 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
150 *err_msg = "Invalid struct statement.";
155 s->name = strdup(tokens[1]);
160 *err_msg = "Memory allocation failed.";
165 *block_mask |= 1 << STRUCT_BLOCK;
171 struct_block_parse(struct struct_spec *s,
172 uint32_t *block_mask,
177 const char **err_msg)
179 struct rte_swx_field_params *new_fields;
180 char *p = tokens[0], *name = NULL;
182 int varbit = 0, error = 0, error_size_invalid = 0, error_varbit_not_last = 0;
184 /* Handle end of block. */
185 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
186 *block_mask &= ~(1 << STRUCT_BLOCK);
198 error_varbit_not_last = 1;
202 if (!strncmp(p, "bit<", strlen("bit<"))) {
203 size_t len = strlen(p);
205 if ((len < strlen("bit< >")) || (p[len - 1] != '>')) {
210 /* Remove the "bit<" and ">". */
211 p[strlen(p) - 1] = 0;
213 } else if (!strncmp(p, "varbit<", strlen("varbit<"))) {
214 size_t len = strlen(p);
216 if ((len < strlen("varbit< >")) || (p[len - 1] != '>')) {
221 /* Remove the "varbit<" and ">". */
222 p[strlen(p) - 1] = 0;
223 p += strlen("varbit<");
225 /* Set the varbit flag. */
232 n_bits = strtoul(p, &p, 0);
236 ((n_bits > 64) && !varbit)) {
238 error_size_invalid = 1;
243 name = strdup(tokens[1]);
249 new_fields = realloc(s->fields, (s->n_fields + 1) * sizeof(struct rte_swx_field_params));
255 s->fields = new_fields;
256 s->fields[s->n_fields].name = name;
257 s->fields[s->n_fields].n_bits = n_bits;
270 *err_msg = "Invalid struct field statement.";
272 if ((error == -EINVAL) && error_varbit_not_last)
273 *err_msg = "Varbit field is not the last struct field.";
275 if ((error == -EINVAL) && error_size_invalid)
276 *err_msg = "Invalid struct field size.";
278 if (error == -ENOMEM)
279 *err_msg = "Memory allocation failed.";
288 * header HEADER_NAME instanceof STRUCT_TYPE_NAME
292 char *struct_type_name;
296 header_spec_free(struct header_spec *s)
304 free(s->struct_type_name);
305 s->struct_type_name = NULL;
309 header_statement_parse(struct header_spec *s,
314 const char **err_msg)
317 if ((n_tokens != 4) || strcmp(tokens[2], "instanceof")) {
321 *err_msg = "Invalid header statement.";
326 s->name = strdup(tokens[1]);
327 s->struct_type_name = strdup(tokens[3]);
329 if (!s->name || !s->struct_type_name) {
331 free(s->struct_type_name);
336 *err_msg = "Memory allocation failed.";
346 * metadata instanceof STRUCT_TYPE_NAME
348 struct metadata_spec {
349 char *struct_type_name;
353 metadata_spec_free(struct metadata_spec *s)
358 free(s->struct_type_name);
359 s->struct_type_name = NULL;
363 metadata_statement_parse(struct metadata_spec *s,
368 const char **err_msg)
371 if ((n_tokens != 3) || strcmp(tokens[1], "instanceof")) {
375 *err_msg = "Invalid metadata statement.";
380 s->struct_type_name = strdup(tokens[2]);
381 if (!s->struct_type_name) {
385 *err_msg = "Memory allocation failed.";
395 * action ACTION_NAME args none | instanceof STRUCT_TYPE_NAME {
402 char *args_struct_type_name;
403 const char **instructions;
404 uint32_t n_instructions;
408 action_spec_free(struct action_spec *s)
418 free(s->args_struct_type_name);
419 s->args_struct_type_name = NULL;
421 for (i = 0; i < s->n_instructions; i++) {
422 uintptr_t instr = (uintptr_t)s->instructions[i];
427 free(s->instructions);
428 s->instructions = NULL;
430 s->n_instructions = 0;
434 action_statement_parse(struct action_spec *s,
435 uint32_t *block_mask,
440 const char **err_msg)
443 if (((n_tokens != 5) && (n_tokens != 6)) ||
445 (strcmp(tokens[2], "args") ||
446 strcmp(tokens[3], "none") ||
447 strcmp(tokens[4], "{"))) ||
449 (strcmp(tokens[2], "args") ||
450 strcmp(tokens[3], "instanceof") ||
451 strcmp(tokens[5], "{")))) {
455 *err_msg = "Invalid action statement.";
460 s->name = strdup(tokens[1]);
461 s->args_struct_type_name = (n_tokens == 6) ? strdup(tokens[4]) : NULL;
463 if ((!s->name) || ((n_tokens == 6) && !s->args_struct_type_name)) {
467 *err_msg = "Memory allocation failed.";
472 *block_mask |= 1 << ACTION_BLOCK;
478 action_block_parse(struct action_spec *s,
479 uint32_t *block_mask,
484 const char **err_msg)
486 char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr;
487 const char **new_instructions;
490 /* Handle end of block. */
491 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
492 *block_mask &= ~(1 << ACTION_BLOCK);
498 for (i = 0; i < n_tokens; i++) {
501 strcat(buffer, tokens[i]);
504 instr = strdup(buffer);
509 *err_msg = "Memory allocation failed.";
513 new_instructions = realloc(s->instructions,
514 (s->n_instructions + 1) * sizeof(char *));
515 if (!new_instructions) {
521 *err_msg = "Memory allocation failed.";
525 s->instructions = new_instructions;
526 s->instructions[s->n_instructions] = instr;
537 * MATCH_FIELD_NAME exact | wildcard | lpm
541 * ACTION_NAME [ @tableonly | @defaultonly ]
544 * default_action ACTION_NAME args none | ARGS_BYTE_ARRAY [ const ]
545 * instanceof TABLE_TYPE_NAME
552 struct rte_swx_pipeline_table_params params;
553 char *recommended_table_type_name;
559 table_spec_free(struct table_spec *s)
561 uintptr_t default_action_name;
570 for (i = 0; i < s->params.n_fields; i++) {
571 uintptr_t name = (uintptr_t)s->params.fields[i].name;
576 free(s->params.fields);
577 s->params.fields = NULL;
579 s->params.n_fields = 0;
581 for (i = 0; i < s->params.n_actions; i++) {
582 uintptr_t name = (uintptr_t)s->params.action_names[i];
587 free(s->params.action_names);
588 s->params.action_names = NULL;
590 s->params.n_actions = 0;
592 default_action_name = (uintptr_t)s->params.default_action_name;
593 free((void *)default_action_name);
594 s->params.default_action_name = NULL;
596 free(s->params.default_action_data);
597 s->params.default_action_data = NULL;
599 free(s->params.action_is_for_table_entries);
600 s->params.action_is_for_table_entries = NULL;
602 free(s->params.action_is_for_default_entry);
603 s->params.action_is_for_default_entry = NULL;
605 s->params.default_action_is_const = 0;
607 free(s->recommended_table_type_name);
608 s->recommended_table_type_name = NULL;
617 table_key_statement_parse(uint32_t *block_mask,
622 const char **err_msg)
625 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
629 *err_msg = "Invalid key statement.";
634 *block_mask |= 1 << TABLE_KEY_BLOCK;
640 table_key_block_parse(struct table_spec *s,
641 uint32_t *block_mask,
646 const char **err_msg)
648 struct rte_swx_match_field_params *new_fields;
649 enum rte_swx_table_match_type match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
652 /* Handle end of block. */
653 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
654 *block_mask &= ~(1 << TABLE_KEY_BLOCK);
658 /* Check input arguments. */
659 if ((n_tokens != 2) ||
660 (strcmp(tokens[1], "exact") &&
661 strcmp(tokens[1], "wildcard") &&
662 strcmp(tokens[1], "lpm"))) {
666 *err_msg = "Invalid match field statement.";
670 if (!strcmp(tokens[1], "wildcard"))
671 match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
672 if (!strcmp(tokens[1], "lpm"))
673 match_type = RTE_SWX_TABLE_MATCH_LPM;
674 if (!strcmp(tokens[1], "exact"))
675 match_type = RTE_SWX_TABLE_MATCH_EXACT;
677 name = strdup(tokens[0]);
682 *err_msg = "Memory allocation failed.";
686 new_fields = realloc(s->params.fields,
687 (s->params.n_fields + 1) * sizeof(struct rte_swx_match_field_params));
694 *err_msg = "Memory allocation failed.";
698 s->params.fields = new_fields;
699 s->params.fields[s->params.n_fields].name = name;
700 s->params.fields[s->params.n_fields].match_type = match_type;
701 s->params.n_fields++;
707 table_actions_statement_parse(uint32_t *block_mask,
712 const char **err_msg)
715 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
719 *err_msg = "Invalid actions statement.";
724 *block_mask |= 1 << TABLE_ACTIONS_BLOCK;
730 table_actions_block_parse(struct table_spec *s,
731 uint32_t *block_mask,
736 const char **err_msg)
738 const char **new_action_names = NULL;
739 int *new_action_is_for_table_entries = NULL, *new_action_is_for_default_entry = NULL;
741 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
743 /* Handle end of block. */
744 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
745 *block_mask &= ~(1 << TABLE_ACTIONS_BLOCK);
749 /* Check input arguments. */
750 if ((n_tokens > 2) ||
751 ((n_tokens == 2) && strcmp(tokens[1], "@tableonly") &&
752 strcmp(tokens[1], "@defaultonly"))) {
756 *err_msg = "Invalid action name statement.";
760 name = strdup(tokens[0]);
763 if (!strcmp(tokens[1], "@tableonly"))
764 action_is_for_default_entry = 0;
766 if (!strcmp(tokens[1], "@defaultonly"))
767 action_is_for_table_entries = 0;
770 new_action_names = realloc(s->params.action_names,
771 (s->params.n_actions + 1) * sizeof(char *));
772 new_action_is_for_table_entries = realloc(s->params.action_is_for_table_entries,
773 (s->params.n_actions + 1) * sizeof(int));
774 new_action_is_for_default_entry = realloc(s->params.action_is_for_default_entry,
775 (s->params.n_actions + 1) * sizeof(int));
779 !new_action_is_for_table_entries ||
780 !new_action_is_for_default_entry) {
782 free(new_action_names);
783 free(new_action_is_for_table_entries);
784 free(new_action_is_for_default_entry);
789 *err_msg = "Memory allocation failed.";
793 s->params.action_names = new_action_names;
794 s->params.action_names[s->params.n_actions] = name;
796 s->params.action_is_for_table_entries = new_action_is_for_table_entries;
797 s->params.action_is_for_table_entries[s->params.n_actions] = action_is_for_table_entries;
799 s->params.action_is_for_default_entry = new_action_is_for_default_entry;
800 s->params.action_is_for_default_entry[s->params.n_actions] = action_is_for_default_entry;
802 s->params.n_actions++;
808 table_statement_parse(struct table_spec *s,
809 uint32_t *block_mask,
814 const char **err_msg)
817 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
821 *err_msg = "Invalid table statement.";
826 s->name = strdup(tokens[1]);
831 *err_msg = "Memory allocation failed.";
836 *block_mask |= 1 << TABLE_BLOCK;
842 table_block_parse(struct table_spec *s,
843 uint32_t *block_mask,
848 const char **err_msg)
850 if (*block_mask & (1 << TABLE_KEY_BLOCK))
851 return table_key_block_parse(s,
859 if (*block_mask & (1 << TABLE_ACTIONS_BLOCK))
860 return table_actions_block_parse(s,
868 /* Handle end of block. */
869 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
870 *block_mask &= ~(1 << TABLE_BLOCK);
874 if (!strcmp(tokens[0], "key"))
875 return table_key_statement_parse(block_mask,
882 if (!strcmp(tokens[0], "actions"))
883 return table_actions_statement_parse(block_mask,
890 if (!strcmp(tokens[0], "default_action")) {
891 if (((n_tokens != 4) && (n_tokens != 5)) ||
892 strcmp(tokens[2], "args") ||
893 strcmp(tokens[3], "none") ||
894 ((n_tokens == 5) && strcmp(tokens[4], "const"))) {
898 *err_msg = "Invalid default_action statement.";
902 if (s->params.default_action_name) {
906 *err_msg = "Duplicate default_action stmt.";
910 s->params.default_action_name = strdup(tokens[1]);
911 if (!s->params.default_action_name) {
915 *err_msg = "Memory allocation failed.";
920 s->params.default_action_is_const = 1;
925 if (!strcmp(tokens[0], "instanceof")) {
930 *err_msg = "Invalid instanceof statement.";
934 if (s->recommended_table_type_name) {
938 *err_msg = "Duplicate instanceof statement.";
942 s->recommended_table_type_name = strdup(tokens[1]);
943 if (!s->recommended_table_type_name) {
947 *err_msg = "Memory allocation failed.";
954 if (!strcmp(tokens[0], "pragma")) {
959 *err_msg = "Invalid pragma statement.";
967 *err_msg = "Duplicate pragma statement.";
971 s->args = strdup(tokens[1]);
976 *err_msg = "Memory allocation failed.";
983 if (!strcmp(tokens[0], "size")) {
990 *err_msg = "Invalid pragma statement.";
994 s->size = strtoul(p, &p, 0);
999 *err_msg = "Invalid size argument.";
1006 /* Anything else. */
1008 *err_line = n_lines;
1010 *err_msg = "Invalid statement.";
1017 * selector SELECTOR_NAME {
1018 * group_id FIELD_NAME
1023 * member_id FIELD_NAME
1025 * n_members_per_group N_MEMBERS_PER_GROUP
1028 struct selector_spec {
1030 struct rte_swx_pipeline_selector_params params;
1034 selector_spec_free(struct selector_spec *s)
1036 uintptr_t field_name;
1046 /* params->group_id_field_name. */
1047 field_name = (uintptr_t)s->params.group_id_field_name;
1048 free((void *)field_name);
1049 s->params.group_id_field_name = NULL;
1051 /* params->selector_field_names. */
1052 for (i = 0; i < s->params.n_selector_fields; i++) {
1053 field_name = (uintptr_t)s->params.selector_field_names[i];
1055 free((void *)field_name);
1058 free(s->params.selector_field_names);
1059 s->params.selector_field_names = NULL;
1061 s->params.n_selector_fields = 0;
1063 /* params->member_id_field_name. */
1064 field_name = (uintptr_t)s->params.member_id_field_name;
1065 free((void *)field_name);
1066 s->params.member_id_field_name = NULL;
1068 /* params->n_groups_max. */
1069 s->params.n_groups_max = 0;
1071 /* params->n_members_per_group_max. */
1072 s->params.n_members_per_group_max = 0;
1076 selector_statement_parse(struct selector_spec *s,
1077 uint32_t *block_mask,
1082 const char **err_msg)
1085 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
1087 *err_line = n_lines;
1089 *err_msg = "Invalid selector statement.";
1094 s->name = strdup(tokens[1]);
1097 *err_line = n_lines;
1099 *err_msg = "Memory allocation failed.";
1104 *block_mask |= 1 << SELECTOR_BLOCK;
1110 selector_selector_statement_parse(uint32_t *block_mask,
1115 const char **err_msg)
1118 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1120 *err_line = n_lines;
1122 *err_msg = "Invalid selector statement.";
1127 *block_mask |= 1 << SELECTOR_SELECTOR_BLOCK;
1133 selector_selector_block_parse(struct selector_spec *s,
1134 uint32_t *block_mask,
1139 const char **err_msg)
1141 const char **new_fields;
1144 /* Handle end of block. */
1145 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1146 *block_mask &= ~(1 << SELECTOR_SELECTOR_BLOCK);
1150 /* Check input arguments. */
1151 if (n_tokens != 1) {
1153 *err_line = n_lines;
1155 *err_msg = "Invalid selector field statement.";
1159 name = strdup(tokens[0]);
1162 *err_line = n_lines;
1164 *err_msg = "Memory allocation failed.";
1168 new_fields = realloc(s->params.selector_field_names,
1169 (s->params.n_selector_fields + 1) * sizeof(char *));
1174 *err_line = n_lines;
1176 *err_msg = "Memory allocation failed.";
1180 s->params.selector_field_names = new_fields;
1181 s->params.selector_field_names[s->params.n_selector_fields] = name;
1182 s->params.n_selector_fields++;
1188 selector_block_parse(struct selector_spec *s,
1189 uint32_t *block_mask,
1194 const char **err_msg)
1196 if (*block_mask & (1 << SELECTOR_SELECTOR_BLOCK))
1197 return selector_selector_block_parse(s,
1205 /* Handle end of block. */
1206 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1207 *block_mask &= ~(1 << SELECTOR_BLOCK);
1211 if (!strcmp(tokens[0], "group_id")) {
1212 if (n_tokens != 2) {
1214 *err_line = n_lines;
1216 *err_msg = "Invalid group_id statement.";
1220 s->params.group_id_field_name = strdup(tokens[1]);
1221 if (!s->params.group_id_field_name) {
1223 *err_line = n_lines;
1225 *err_msg = "Memory allocation failed.";
1232 if (!strcmp(tokens[0], "selector"))
1233 return selector_selector_statement_parse(block_mask,
1240 if (!strcmp(tokens[0], "member_id")) {
1241 if (n_tokens != 2) {
1243 *err_line = n_lines;
1245 *err_msg = "Invalid member_id statement.";
1249 s->params.member_id_field_name = strdup(tokens[1]);
1250 if (!s->params.member_id_field_name) {
1252 *err_line = n_lines;
1254 *err_msg = "Memory allocation failed.";
1261 if (!strcmp(tokens[0], "n_groups_max")) {
1262 char *p = tokens[1];
1264 if (n_tokens != 2) {
1266 *err_line = n_lines;
1268 *err_msg = "Invalid n_groups statement.";
1272 s->params.n_groups_max = strtoul(p, &p, 0);
1275 *err_line = n_lines;
1277 *err_msg = "Invalid n_groups argument.";
1284 if (!strcmp(tokens[0], "n_members_per_group_max")) {
1285 char *p = tokens[1];
1287 if (n_tokens != 2) {
1289 *err_line = n_lines;
1291 *err_msg = "Invalid n_members_per_group statement.";
1295 s->params.n_members_per_group_max = strtoul(p, &p, 0);
1298 *err_line = n_lines;
1300 *err_msg = "Invalid n_members_per_group argument.";
1307 /* Anything else. */
1309 *err_line = n_lines;
1311 *err_msg = "Invalid statement.";
1324 * ACTION_NAME [ @tableonly | @defaultonly]
1327 * default_action ACTION_NAME args none | ARGS_BYTE_ARRAY [ const ]
1329 * timeout TIMEOUT_IN_SECONDS
1332 struct learner_spec {
1334 struct rte_swx_pipeline_learner_params params;
1340 learner_spec_free(struct learner_spec *s)
1342 uintptr_t default_action_name;
1351 for (i = 0; i < s->params.n_fields; i++) {
1352 uintptr_t name = (uintptr_t)s->params.field_names[i];
1357 free(s->params.field_names);
1358 s->params.field_names = NULL;
1360 s->params.n_fields = 0;
1362 for (i = 0; i < s->params.n_actions; i++) {
1363 uintptr_t name = (uintptr_t)s->params.action_names[i];
1368 free(s->params.action_names);
1369 s->params.action_names = NULL;
1371 s->params.n_actions = 0;
1373 default_action_name = (uintptr_t)s->params.default_action_name;
1374 free((void *)default_action_name);
1375 s->params.default_action_name = NULL;
1377 free(s->params.default_action_data);
1378 s->params.default_action_data = NULL;
1380 free(s->params.action_is_for_table_entries);
1381 s->params.action_is_for_table_entries = NULL;
1383 free(s->params.action_is_for_default_entry);
1384 s->params.action_is_for_default_entry = NULL;
1386 s->params.default_action_is_const = 0;
1394 learner_key_statement_parse(uint32_t *block_mask,
1399 const char **err_msg)
1402 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1404 *err_line = n_lines;
1406 *err_msg = "Invalid key statement.";
1411 *block_mask |= 1 << LEARNER_KEY_BLOCK;
1417 learner_key_block_parse(struct learner_spec *s,
1418 uint32_t *block_mask,
1423 const char **err_msg)
1425 const char **new_field_names = NULL;
1426 char *field_name = NULL;
1428 /* Handle end of block. */
1429 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1430 *block_mask &= ~(1 << LEARNER_KEY_BLOCK);
1434 /* Check input arguments. */
1435 if (n_tokens != 1) {
1437 *err_line = n_lines;
1439 *err_msg = "Invalid match field statement.";
1443 field_name = strdup(tokens[0]);
1444 new_field_names = realloc(s->params.field_names, (s->params.n_fields + 1) * sizeof(char *));
1445 if (!field_name || !new_field_names) {
1447 free(new_field_names);
1450 *err_line = n_lines;
1452 *err_msg = "Memory allocation failed.";
1456 s->params.field_names = new_field_names;
1457 s->params.field_names[s->params.n_fields] = field_name;
1458 s->params.n_fields++;
1464 learner_actions_statement_parse(uint32_t *block_mask,
1469 const char **err_msg)
1472 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1474 *err_line = n_lines;
1476 *err_msg = "Invalid actions statement.";
1481 *block_mask |= 1 << LEARNER_ACTIONS_BLOCK;
1487 learner_actions_block_parse(struct learner_spec *s,
1488 uint32_t *block_mask,
1493 const char **err_msg)
1495 const char **new_action_names = NULL;
1496 int *new_action_is_for_table_entries = NULL, *new_action_is_for_default_entry = NULL;
1498 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
1500 /* Handle end of block. */
1501 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1502 *block_mask &= ~(1 << LEARNER_ACTIONS_BLOCK);
1506 /* Check input arguments. */
1507 if ((n_tokens > 2) ||
1508 ((n_tokens == 2) && strcmp(tokens[1], "@tableonly") &&
1509 strcmp(tokens[1], "@defaultonly"))) {
1511 *err_line = n_lines;
1513 *err_msg = "Invalid action name statement.";
1517 name = strdup(tokens[0]);
1519 if (n_tokens == 2) {
1520 if (!strcmp(tokens[1], "@tableonly"))
1521 action_is_for_default_entry = 0;
1523 if (!strcmp(tokens[1], "@defaultonly"))
1524 action_is_for_table_entries = 0;
1527 new_action_names = realloc(s->params.action_names,
1528 (s->params.n_actions + 1) * sizeof(char *));
1529 new_action_is_for_table_entries = realloc(s->params.action_is_for_table_entries,
1530 (s->params.n_actions + 1) * sizeof(int));
1531 new_action_is_for_default_entry = realloc(s->params.action_is_for_default_entry,
1532 (s->params.n_actions + 1) * sizeof(int));
1535 !new_action_names ||
1536 !new_action_is_for_table_entries ||
1537 !new_action_is_for_default_entry) {
1539 free(new_action_names);
1540 free(new_action_is_for_table_entries);
1541 free(new_action_is_for_default_entry);
1544 *err_line = n_lines;
1546 *err_msg = "Memory allocation failed.";
1550 s->params.action_names = new_action_names;
1551 s->params.action_names[s->params.n_actions] = name;
1553 s->params.action_is_for_table_entries = new_action_is_for_table_entries;
1554 s->params.action_is_for_table_entries[s->params.n_actions] = action_is_for_table_entries;
1556 s->params.action_is_for_default_entry = new_action_is_for_default_entry;
1557 s->params.action_is_for_default_entry[s->params.n_actions] = action_is_for_default_entry;
1559 s->params.n_actions++;
1565 learner_statement_parse(struct learner_spec *s,
1566 uint32_t *block_mask,
1571 const char **err_msg)
1574 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
1576 *err_line = n_lines;
1578 *err_msg = "Invalid learner statement.";
1583 s->name = strdup(tokens[1]);
1586 *err_line = n_lines;
1588 *err_msg = "Memory allocation failed.";
1593 *block_mask |= 1 << LEARNER_BLOCK;
1599 learner_block_parse(struct learner_spec *s,
1600 uint32_t *block_mask,
1605 const char **err_msg)
1607 if (*block_mask & (1 << LEARNER_KEY_BLOCK))
1608 return learner_key_block_parse(s,
1616 if (*block_mask & (1 << LEARNER_ACTIONS_BLOCK))
1617 return learner_actions_block_parse(s,
1625 /* Handle end of block. */
1626 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1627 *block_mask &= ~(1 << LEARNER_BLOCK);
1631 if (!strcmp(tokens[0], "key"))
1632 return learner_key_statement_parse(block_mask,
1639 if (!strcmp(tokens[0], "actions"))
1640 return learner_actions_statement_parse(block_mask,
1647 if (!strcmp(tokens[0], "default_action")) {
1648 if (((n_tokens != 4) && (n_tokens != 5)) ||
1649 strcmp(tokens[2], "args") ||
1650 strcmp(tokens[3], "none") ||
1651 ((n_tokens == 5) && strcmp(tokens[4], "const"))) {
1653 *err_line = n_lines;
1655 *err_msg = "Invalid default_action statement.";
1659 if (s->params.default_action_name) {
1661 *err_line = n_lines;
1663 *err_msg = "Duplicate default_action stmt.";
1667 s->params.default_action_name = strdup(tokens[1]);
1668 if (!s->params.default_action_name) {
1670 *err_line = n_lines;
1672 *err_msg = "Memory allocation failed.";
1677 s->params.default_action_is_const = 1;
1682 if (!strcmp(tokens[0], "size")) {
1683 char *p = tokens[1];
1685 if (n_tokens != 2) {
1687 *err_line = n_lines;
1689 *err_msg = "Invalid size statement.";
1693 s->size = strtoul(p, &p, 0);
1696 *err_line = n_lines;
1698 *err_msg = "Invalid size argument.";
1705 if (!strcmp(tokens[0], "timeout")) {
1706 char *p = tokens[1];
1708 if (n_tokens != 2) {
1710 *err_line = n_lines;
1712 *err_msg = "Invalid timeout statement.";
1716 s->timeout = strtoul(p, &p, 0);
1719 *err_line = n_lines;
1721 *err_msg = "Invalid timeout argument.";
1728 /* Anything else. */
1730 *err_line = n_lines;
1732 *err_msg = "Invalid statement.";
1739 * regarray NAME size SIZE initval INITVAL
1741 struct regarray_spec {
1748 regarray_spec_free(struct regarray_spec *s)
1758 regarray_statement_parse(struct regarray_spec *s,
1763 const char **err_msg)
1768 if ((n_tokens != 6) ||
1769 strcmp(tokens[2], "size") ||
1770 strcmp(tokens[4], "initval")) {
1772 *err_line = n_lines;
1774 *err_msg = "Invalid regarray statement.";
1779 s->name = strdup(tokens[1]);
1782 *err_line = n_lines;
1784 *err_msg = "Memory allocation failed.";
1789 s->size = strtoul(p, &p, 0);
1790 if (p[0] || !s->size) {
1792 *err_line = n_lines;
1794 *err_msg = "Invalid size argument.";
1799 s->init_val = strtoull(p, &p, 0);
1802 *err_line = n_lines;
1804 *err_msg = "Invalid initval argument.";
1814 * metarray NAME size SIZE
1816 struct metarray_spec {
1822 metarray_spec_free(struct metarray_spec *s)
1832 metarray_statement_parse(struct metarray_spec *s,
1837 const char **err_msg)
1842 if ((n_tokens != 4) || strcmp(tokens[2], "size")) {
1844 *err_line = n_lines;
1846 *err_msg = "Invalid metarray statement.";
1851 s->name = strdup(tokens[1]);
1854 *err_line = n_lines;
1856 *err_msg = "Memory allocation failed.";
1861 s->size = strtoul(p, &p, 0);
1862 if (p[0] || !s->size) {
1864 *err_line = n_lines;
1866 *err_msg = "Invalid size argument.";
1882 const char **instructions;
1883 uint32_t n_instructions;
1887 apply_spec_free(struct apply_spec *s)
1894 for (i = 0; i < s->n_instructions; i++) {
1895 uintptr_t instr = (uintptr_t)s->instructions[i];
1897 free((void *)instr);
1900 free(s->instructions);
1901 s->instructions = NULL;
1903 s->n_instructions = 0;
1907 apply_statement_parse(uint32_t *block_mask,
1912 const char **err_msg)
1915 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1917 *err_line = n_lines;
1919 *err_msg = "Invalid apply statement.";
1924 *block_mask |= 1 << APPLY_BLOCK;
1930 apply_block_parse(struct apply_spec *s,
1931 uint32_t *block_mask,
1936 const char **err_msg)
1938 char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr;
1939 const char **new_instructions;
1942 /* Handle end of block. */
1943 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1944 *block_mask &= ~(1 << APPLY_BLOCK);
1950 for (i = 0; i < n_tokens; i++) {
1952 strcat(buffer, " ");
1953 strcat(buffer, tokens[i]);
1956 instr = strdup(buffer);
1959 *err_line = n_lines;
1961 *err_msg = "Memory allocation failed.";
1965 new_instructions = realloc(s->instructions,
1966 (s->n_instructions + 1) * sizeof(char *));
1967 if (!new_instructions) {
1971 *err_line = n_lines;
1973 *err_msg = "Memory allocation failed.";
1977 s->instructions = new_instructions;
1978 s->instructions[s->n_instructions] = instr;
1979 s->n_instructions++;
1988 rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
1991 const char **err_msg)
1993 struct extobj_spec extobj_spec = {0};
1994 struct struct_spec struct_spec = {0};
1995 struct header_spec header_spec = {0};
1996 struct metadata_spec metadata_spec = {0};
1997 struct action_spec action_spec = {0};
1998 struct table_spec table_spec = {0};
1999 struct selector_spec selector_spec = {0};
2000 struct learner_spec learner_spec = {0};
2001 struct regarray_spec regarray_spec = {0};
2002 struct metarray_spec metarray_spec = {0};
2003 struct apply_spec apply_spec = {0};
2005 uint32_t block_mask = 0;
2008 /* Check the input arguments. */
2013 *err_msg = "Null pipeline argument.";
2022 *err_msg = "Null specification file argument.";
2027 for (n_lines = 1; ; n_lines++) {
2028 char line[MAX_LINE_LENGTH];
2029 char *tokens[MAX_TOKENS], *ptr = line;
2030 uint32_t n_tokens = 0;
2032 /* Read next line. */
2033 if (!fgets(line, sizeof(line), spec))
2036 /* Parse the line into tokens. */
2041 token = strtok_r(ptr, " \f\n\r\t\v", &ptr);
2045 /* Handle comments. */
2046 if ((token[0] == '#') ||
2047 (token[0] == ';') ||
2048 ((token[0] == '/') && (token[1] == '/'))) {
2052 /* Handle excessively long lines. */
2053 if (n_tokens >= MAX_TOKENS) {
2055 *err_line = n_lines;
2057 *err_msg = "Too many tokens.";
2062 /* Handle excessively long tokens. */
2063 if (strnlen(token, RTE_SWX_NAME_SIZE) >=
2064 RTE_SWX_NAME_SIZE) {
2066 *err_line = n_lines;
2068 *err_msg = "Token too big.";
2074 tokens[n_tokens] = token;
2078 /* Handle empty lines. */
2083 if (block_mask & (1 << STRUCT_BLOCK)) {
2084 status = struct_block_parse(&struct_spec,
2094 if (block_mask & (1 << STRUCT_BLOCK))
2098 status = rte_swx_pipeline_struct_type_register(p,
2101 struct_spec.n_fields,
2102 struct_spec.varbit);
2105 *err_line = n_lines;
2107 *err_msg = "Struct registration error.";
2111 struct_spec_free(&struct_spec);
2117 if (block_mask & (1 << ACTION_BLOCK)) {
2118 status = action_block_parse(&action_spec,
2128 if (block_mask & (1 << ACTION_BLOCK))
2132 status = rte_swx_pipeline_action_config(p,
2134 action_spec.args_struct_type_name,
2135 action_spec.instructions,
2136 action_spec.n_instructions);
2139 *err_line = n_lines;
2141 *err_msg = "Action config error.";
2145 action_spec_free(&action_spec);
2151 if (block_mask & (1 << TABLE_BLOCK)) {
2152 status = table_block_parse(&table_spec,
2162 if (block_mask & (1 << TABLE_BLOCK))
2166 status = rte_swx_pipeline_table_config(p,
2169 table_spec.recommended_table_type_name,
2174 *err_line = n_lines;
2176 *err_msg = "Table configuration error.";
2180 table_spec_free(&table_spec);
2185 /* selector block. */
2186 if (block_mask & (1 << SELECTOR_BLOCK)) {
2187 status = selector_block_parse(&selector_spec,
2197 if (block_mask & (1 << SELECTOR_BLOCK))
2201 status = rte_swx_pipeline_selector_config(p,
2203 &selector_spec.params);
2206 *err_line = n_lines;
2208 *err_msg = "Selector configuration error.";
2212 selector_spec_free(&selector_spec);
2217 /* learner block. */
2218 if (block_mask & (1 << LEARNER_BLOCK)) {
2219 status = learner_block_parse(&learner_spec,
2229 if (block_mask & (1 << LEARNER_BLOCK))
2233 status = rte_swx_pipeline_learner_config(p,
2235 &learner_spec.params,
2237 learner_spec.timeout);
2240 *err_line = n_lines;
2242 *err_msg = "Learner table configuration error.";
2246 learner_spec_free(&learner_spec);
2252 if (block_mask & (1 << APPLY_BLOCK)) {
2253 status = apply_block_parse(&apply_spec,
2263 if (block_mask & (1 << APPLY_BLOCK))
2267 status = rte_swx_pipeline_instructions_config(p,
2268 apply_spec.instructions,
2269 apply_spec.n_instructions);
2272 *err_line = n_lines;
2274 *err_msg = "Pipeline instructions err.";
2278 apply_spec_free(&apply_spec);
2284 if (!strcmp(tokens[0], "extobj")) {
2285 status = extobj_statement_parse(&extobj_spec,
2294 status = rte_swx_pipeline_extern_object_config(p,
2296 extobj_spec.extern_type_name,
2297 extobj_spec.pragma);
2300 *err_line = n_lines;
2302 *err_msg = "Extern object config err.";
2306 extobj_spec_free(&extobj_spec);
2312 if (!strcmp(tokens[0], "struct")) {
2313 status = struct_statement_parse(&struct_spec,
2327 if (!strcmp(tokens[0], "header")) {
2328 status = header_statement_parse(&header_spec,
2337 status = rte_swx_pipeline_packet_header_register(p,
2339 header_spec.struct_type_name);
2342 *err_line = n_lines;
2344 *err_msg = "Header registration error.";
2348 header_spec_free(&header_spec);
2354 if (!strcmp(tokens[0], "metadata")) {
2355 status = metadata_statement_parse(&metadata_spec,
2364 status = rte_swx_pipeline_packet_metadata_register(p,
2365 metadata_spec.struct_type_name);
2368 *err_line = n_lines;
2370 *err_msg = "Meta-data reg err.";
2374 metadata_spec_free(&metadata_spec);
2380 if (!strcmp(tokens[0], "action")) {
2381 status = action_statement_parse(&action_spec,
2395 if (!strcmp(tokens[0], "table")) {
2396 status = table_statement_parse(&table_spec,
2410 if (!strcmp(tokens[0], "selector")) {
2411 status = selector_statement_parse(&selector_spec,
2425 if (!strcmp(tokens[0], "learner")) {
2426 status = learner_statement_parse(&learner_spec,
2440 if (!strcmp(tokens[0], "regarray")) {
2441 status = regarray_statement_parse(®array_spec,
2450 status = rte_swx_pipeline_regarray_config(p,
2453 regarray_spec.init_val);
2456 *err_line = n_lines;
2458 *err_msg = "Register array configuration error.";
2462 regarray_spec_free(®array_spec);
2468 if (!strcmp(tokens[0], "metarray")) {
2469 status = metarray_statement_parse(&metarray_spec,
2478 status = rte_swx_pipeline_metarray_config(p,
2480 metarray_spec.size);
2483 *err_line = n_lines;
2485 *err_msg = "Meter array configuration error.";
2489 metarray_spec_free(&metarray_spec);
2495 if (!strcmp(tokens[0], "apply")) {
2496 status = apply_statement_parse(&block_mask,
2508 /* Anything else. */
2510 *err_line = n_lines;
2512 *err_msg = "Unknown statement.";
2517 /* Handle unfinished block. */
2520 *err_line = n_lines;
2522 *err_msg = "Missing }.";
2527 /* Pipeline build. */
2528 status = rte_swx_pipeline_build(p);
2531 *err_line = n_lines;
2533 *err_msg = "Pipeline build error.";
2540 extobj_spec_free(&extobj_spec);
2541 struct_spec_free(&struct_spec);
2542 header_spec_free(&header_spec);
2543 metadata_spec_free(&metadata_spec);
2544 action_spec_free(&action_spec);
2545 table_spec_free(&table_spec);
2546 selector_spec_free(&selector_spec);
2547 learner_spec_free(&learner_spec);
2548 regarray_spec_free(®array_spec);
2549 metarray_spec_free(&metarray_spec);
2550 apply_spec_free(&apply_spec);