1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2020 Intel Corporation
10 #include <rte_common.h>
12 #include "rte_swx_pipeline.h"
14 #ifndef MAX_LINE_LENGTH
15 #define MAX_LINE_LENGTH 2048
19 #define MAX_TOKENS 256
22 #define STRUCT_BLOCK 0
23 #define ACTION_BLOCK 1
25 #define TABLE_KEY_BLOCK 3
26 #define TABLE_ACTIONS_BLOCK 4
27 #define SELECTOR_BLOCK 5
28 #define SELECTOR_SELECTOR_BLOCK 6
29 #define LEARNER_BLOCK 7
30 #define LEARNER_KEY_BLOCK 8
31 #define LEARNER_ACTIONS_BLOCK 9
32 #define APPLY_BLOCK 10
37 * extobj OBJ_NAME instanceof OBJ_TYPE [ pragma OBJ_CREATE_ARGS ]
41 char *extern_type_name;
46 extobj_spec_free(struct extobj_spec *s)
54 free(s->extern_type_name);
55 s->extern_type_name = NULL;
62 extobj_statement_parse(struct extobj_spec *s,
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")))) {
77 *err_msg = "Invalid extobj statement.";
82 s->name = strdup(tokens[1]);
83 s->extern_type_name = strdup(tokens[3]);
84 s->pragma = (n_tokens == 6) ? strdup(tokens[5]) : NULL;
87 !s->extern_type_name ||
88 ((n_tokens == 6) && !s->pragma)) {
90 free(s->extern_type_name);
96 *err_msg = "Memory allocation failed.";
106 * struct STRUCT_TYPE_NAME {
107 * bit<SIZE> | varbit<SIZE> FIELD_NAME
113 struct rte_swx_field_params *fields;
119 struct_spec_free(struct struct_spec *s)
129 for (i = 0; i < s->n_fields; i++) {
130 uintptr_t name = (uintptr_t)s->fields[i].name;
144 struct_statement_parse(struct struct_spec *s,
145 uint32_t *block_mask,
150 const char **err_msg)
153 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
157 *err_msg = "Invalid struct statement.";
162 s->name = strdup(tokens[1]);
167 *err_msg = "Memory allocation failed.";
172 *block_mask |= 1 << STRUCT_BLOCK;
178 struct_block_parse(struct struct_spec *s,
179 uint32_t *block_mask,
184 const char **err_msg)
186 struct rte_swx_field_params *new_fields;
187 char *p = tokens[0], *name = NULL;
189 int varbit = 0, error = 0, error_size_invalid = 0, error_varbit_not_last = 0;
191 /* Handle end of block. */
192 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
193 *block_mask &= ~(1 << STRUCT_BLOCK);
205 error_varbit_not_last = 1;
209 if (!strncmp(p, "bit<", strlen("bit<"))) {
210 size_t len = strlen(p);
212 if ((len < strlen("bit< >")) || (p[len - 1] != '>')) {
217 /* Remove the "bit<" and ">". */
218 p[strlen(p) - 1] = 0;
220 } else if (!strncmp(p, "varbit<", strlen("varbit<"))) {
221 size_t len = strlen(p);
223 if ((len < strlen("varbit< >")) || (p[len - 1] != '>')) {
228 /* Remove the "varbit<" and ">". */
229 p[strlen(p) - 1] = 0;
230 p += strlen("varbit<");
232 /* Set the varbit flag. */
239 n_bits = strtoul(p, &p, 0);
243 ((n_bits > 64) && !varbit)) {
245 error_size_invalid = 1;
250 name = strdup(tokens[1]);
256 new_fields = realloc(s->fields, (s->n_fields + 1) * sizeof(struct rte_swx_field_params));
262 s->fields = new_fields;
263 s->fields[s->n_fields].name = name;
264 s->fields[s->n_fields].n_bits = n_bits;
277 *err_msg = "Invalid struct field statement.";
279 if ((error == -EINVAL) && error_varbit_not_last)
280 *err_msg = "Varbit field is not the last struct field.";
282 if ((error == -EINVAL) && error_size_invalid)
283 *err_msg = "Invalid struct field size.";
285 if (error == -ENOMEM)
286 *err_msg = "Memory allocation failed.";
295 * header HEADER_NAME instanceof STRUCT_TYPE_NAME
299 char *struct_type_name;
303 header_spec_free(struct header_spec *s)
311 free(s->struct_type_name);
312 s->struct_type_name = NULL;
316 header_statement_parse(struct header_spec *s,
321 const char **err_msg)
324 if ((n_tokens != 4) || strcmp(tokens[2], "instanceof")) {
328 *err_msg = "Invalid header statement.";
333 s->name = strdup(tokens[1]);
334 s->struct_type_name = strdup(tokens[3]);
336 if (!s->name || !s->struct_type_name) {
338 free(s->struct_type_name);
343 *err_msg = "Memory allocation failed.";
353 * metadata instanceof STRUCT_TYPE_NAME
355 struct metadata_spec {
356 char *struct_type_name;
360 metadata_spec_free(struct metadata_spec *s)
365 free(s->struct_type_name);
366 s->struct_type_name = NULL;
370 metadata_statement_parse(struct metadata_spec *s,
375 const char **err_msg)
378 if ((n_tokens != 3) || strcmp(tokens[1], "instanceof")) {
382 *err_msg = "Invalid metadata statement.";
387 s->struct_type_name = strdup(tokens[2]);
388 if (!s->struct_type_name) {
392 *err_msg = "Memory allocation failed.";
402 * action ACTION_NAME args none | instanceof STRUCT_TYPE_NAME {
409 char *args_struct_type_name;
410 const char **instructions;
411 uint32_t n_instructions;
415 action_spec_free(struct action_spec *s)
425 free(s->args_struct_type_name);
426 s->args_struct_type_name = NULL;
428 for (i = 0; i < s->n_instructions; i++) {
429 uintptr_t instr = (uintptr_t)s->instructions[i];
434 free(s->instructions);
435 s->instructions = NULL;
437 s->n_instructions = 0;
441 action_statement_parse(struct action_spec *s,
442 uint32_t *block_mask,
447 const char **err_msg)
450 if (((n_tokens != 5) && (n_tokens != 6)) ||
452 (strcmp(tokens[2], "args") ||
453 strcmp(tokens[3], "none") ||
454 strcmp(tokens[4], "{"))) ||
456 (strcmp(tokens[2], "args") ||
457 strcmp(tokens[3], "instanceof") ||
458 strcmp(tokens[5], "{")))) {
462 *err_msg = "Invalid action statement.";
467 s->name = strdup(tokens[1]);
468 s->args_struct_type_name = (n_tokens == 6) ? strdup(tokens[4]) : NULL;
470 if ((!s->name) || ((n_tokens == 6) && !s->args_struct_type_name)) {
474 *err_msg = "Memory allocation failed.";
479 *block_mask |= 1 << ACTION_BLOCK;
485 action_block_parse(struct action_spec *s,
486 uint32_t *block_mask,
491 const char **err_msg)
493 char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr;
494 const char **new_instructions;
497 /* Handle end of block. */
498 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
499 *block_mask &= ~(1 << ACTION_BLOCK);
505 for (i = 0; i < n_tokens; i++) {
508 strcat(buffer, tokens[i]);
511 instr = strdup(buffer);
516 *err_msg = "Memory allocation failed.";
520 new_instructions = realloc(s->instructions,
521 (s->n_instructions + 1) * sizeof(char *));
522 if (!new_instructions) {
528 *err_msg = "Memory allocation failed.";
532 s->instructions = new_instructions;
533 s->instructions[s->n_instructions] = instr;
544 * MATCH_FIELD_NAME exact | wildcard | lpm
548 * ACTION_NAME [ @tableonly | @defaultonly ]
551 * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
552 * instanceof TABLE_TYPE_NAME
559 struct rte_swx_pipeline_table_params params;
560 char *recommended_table_type_name;
566 table_spec_free(struct table_spec *s)
568 uintptr_t default_action_name, default_action_args;
577 for (i = 0; i < s->params.n_fields; i++) {
578 uintptr_t name = (uintptr_t)s->params.fields[i].name;
583 free(s->params.fields);
584 s->params.fields = NULL;
586 s->params.n_fields = 0;
588 for (i = 0; i < s->params.n_actions; i++) {
589 uintptr_t name = (uintptr_t)s->params.action_names[i];
594 free(s->params.action_names);
595 s->params.action_names = NULL;
597 s->params.n_actions = 0;
599 default_action_name = (uintptr_t)s->params.default_action_name;
600 free((void *)default_action_name);
601 s->params.default_action_name = NULL;
603 default_action_args = (uintptr_t)s->params.default_action_args;
604 free((void *)default_action_args);
605 s->params.default_action_args = NULL;
607 free(s->params.action_is_for_table_entries);
608 s->params.action_is_for_table_entries = NULL;
610 free(s->params.action_is_for_default_entry);
611 s->params.action_is_for_default_entry = NULL;
613 s->params.default_action_is_const = 0;
615 free(s->recommended_table_type_name);
616 s->recommended_table_type_name = NULL;
625 table_key_statement_parse(uint32_t *block_mask,
630 const char **err_msg)
633 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
637 *err_msg = "Invalid key statement.";
642 *block_mask |= 1 << TABLE_KEY_BLOCK;
648 table_key_block_parse(struct table_spec *s,
649 uint32_t *block_mask,
654 const char **err_msg)
656 struct rte_swx_match_field_params *new_fields;
657 enum rte_swx_table_match_type match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
660 /* Handle end of block. */
661 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
662 *block_mask &= ~(1 << TABLE_KEY_BLOCK);
666 /* Check input arguments. */
667 if ((n_tokens != 2) ||
668 (strcmp(tokens[1], "exact") &&
669 strcmp(tokens[1], "wildcard") &&
670 strcmp(tokens[1], "lpm"))) {
674 *err_msg = "Invalid match field statement.";
678 if (!strcmp(tokens[1], "wildcard"))
679 match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
680 if (!strcmp(tokens[1], "lpm"))
681 match_type = RTE_SWX_TABLE_MATCH_LPM;
682 if (!strcmp(tokens[1], "exact"))
683 match_type = RTE_SWX_TABLE_MATCH_EXACT;
685 name = strdup(tokens[0]);
690 *err_msg = "Memory allocation failed.";
694 new_fields = realloc(s->params.fields,
695 (s->params.n_fields + 1) * sizeof(struct rte_swx_match_field_params));
702 *err_msg = "Memory allocation failed.";
706 s->params.fields = new_fields;
707 s->params.fields[s->params.n_fields].name = name;
708 s->params.fields[s->params.n_fields].match_type = match_type;
709 s->params.n_fields++;
715 table_actions_statement_parse(uint32_t *block_mask,
720 const char **err_msg)
723 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
727 *err_msg = "Invalid actions statement.";
732 *block_mask |= 1 << TABLE_ACTIONS_BLOCK;
738 table_actions_block_parse(struct table_spec *s,
739 uint32_t *block_mask,
744 const char **err_msg)
746 const char **new_action_names = NULL;
747 int *new_action_is_for_table_entries = NULL, *new_action_is_for_default_entry = NULL;
749 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
751 /* Handle end of block. */
752 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
753 *block_mask &= ~(1 << TABLE_ACTIONS_BLOCK);
757 /* Check input arguments. */
758 if ((n_tokens > 2) ||
759 ((n_tokens == 2) && strcmp(tokens[1], "@tableonly") &&
760 strcmp(tokens[1], "@defaultonly"))) {
764 *err_msg = "Invalid action name statement.";
768 name = strdup(tokens[0]);
771 if (!strcmp(tokens[1], "@tableonly"))
772 action_is_for_default_entry = 0;
774 if (!strcmp(tokens[1], "@defaultonly"))
775 action_is_for_table_entries = 0;
778 new_action_names = realloc(s->params.action_names,
779 (s->params.n_actions + 1) * sizeof(char *));
780 new_action_is_for_table_entries = realloc(s->params.action_is_for_table_entries,
781 (s->params.n_actions + 1) * sizeof(int));
782 new_action_is_for_default_entry = realloc(s->params.action_is_for_default_entry,
783 (s->params.n_actions + 1) * sizeof(int));
787 !new_action_is_for_table_entries ||
788 !new_action_is_for_default_entry) {
790 free(new_action_names);
791 free(new_action_is_for_table_entries);
792 free(new_action_is_for_default_entry);
797 *err_msg = "Memory allocation failed.";
801 s->params.action_names = new_action_names;
802 s->params.action_names[s->params.n_actions] = name;
804 s->params.action_is_for_table_entries = new_action_is_for_table_entries;
805 s->params.action_is_for_table_entries[s->params.n_actions] = action_is_for_table_entries;
807 s->params.action_is_for_default_entry = new_action_is_for_default_entry;
808 s->params.action_is_for_default_entry[s->params.n_actions] = action_is_for_default_entry;
810 s->params.n_actions++;
816 table_default_action_statement_parse(struct table_spec *s,
821 const char **err_msg)
824 int status = 0, duplicate = 0;
827 if ((n_tokens < 4) ||
828 strcmp(tokens[2], "args")) {
833 if (s->params.default_action_name) {
839 s->params.default_action_name = strdup(tokens[1]);
840 if (!s->params.default_action_name) {
845 if (strcmp(tokens[3], "none")) {
846 char buffer[MAX_LINE_LENGTH];
847 uint32_t n_tokens_args = n_tokens - 3;
849 if (!strcmp(tokens[n_tokens - 1], "const"))
852 if (!n_tokens_args) {
858 for (i = 0; i < n_tokens_args; i++) {
862 strcat(buffer, tokens[3 + i]);
865 s->params.default_action_args = strdup(buffer);
866 if (!s->params.default_action_args) {
871 if (((n_tokens != 4) && (n_tokens != 5)) ||
872 ((n_tokens == 5) && (strcmp(tokens[4], "const")))) {
878 if (!strcmp(tokens[n_tokens - 1], "const"))
879 s->params.default_action_is_const = 1;
890 *err_msg = "Memory allocation failed.";
895 *err_msg = "Duplicate default_action statement.";
897 *err_msg = "Invalid default_action statement.";
904 table_statement_parse(struct table_spec *s,
905 uint32_t *block_mask,
910 const char **err_msg)
913 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
917 *err_msg = "Invalid table statement.";
922 s->name = strdup(tokens[1]);
927 *err_msg = "Memory allocation failed.";
932 *block_mask |= 1 << TABLE_BLOCK;
938 table_block_parse(struct table_spec *s,
939 uint32_t *block_mask,
944 const char **err_msg)
946 if (*block_mask & (1 << TABLE_KEY_BLOCK))
947 return table_key_block_parse(s,
955 if (*block_mask & (1 << TABLE_ACTIONS_BLOCK))
956 return table_actions_block_parse(s,
964 /* Handle end of block. */
965 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
966 *block_mask &= ~(1 << TABLE_BLOCK);
970 if (!strcmp(tokens[0], "key"))
971 return table_key_statement_parse(block_mask,
978 if (!strcmp(tokens[0], "actions"))
979 return table_actions_statement_parse(block_mask,
986 if (!strcmp(tokens[0], "default_action"))
987 return table_default_action_statement_parse(s,
994 if (!strcmp(tokens[0], "instanceof")) {
999 *err_msg = "Invalid instanceof statement.";
1003 if (s->recommended_table_type_name) {
1005 *err_line = n_lines;
1007 *err_msg = "Duplicate instanceof statement.";
1011 s->recommended_table_type_name = strdup(tokens[1]);
1012 if (!s->recommended_table_type_name) {
1014 *err_line = n_lines;
1016 *err_msg = "Memory allocation failed.";
1023 if (!strcmp(tokens[0], "pragma")) {
1024 if (n_tokens != 2) {
1026 *err_line = n_lines;
1028 *err_msg = "Invalid pragma statement.";
1034 *err_line = n_lines;
1036 *err_msg = "Duplicate pragma statement.";
1040 s->args = strdup(tokens[1]);
1043 *err_line = n_lines;
1045 *err_msg = "Memory allocation failed.";
1052 if (!strcmp(tokens[0], "size")) {
1053 char *p = tokens[1];
1055 if (n_tokens != 2) {
1057 *err_line = n_lines;
1059 *err_msg = "Invalid pragma statement.";
1063 s->size = strtoul(p, &p, 0);
1066 *err_line = n_lines;
1068 *err_msg = "Invalid size argument.";
1075 /* Anything else. */
1077 *err_line = n_lines;
1079 *err_msg = "Invalid statement.";
1086 * selector SELECTOR_NAME {
1087 * group_id FIELD_NAME
1092 * member_id FIELD_NAME
1094 * n_members_per_group N_MEMBERS_PER_GROUP
1097 struct selector_spec {
1099 struct rte_swx_pipeline_selector_params params;
1103 selector_spec_free(struct selector_spec *s)
1105 uintptr_t field_name;
1115 /* params->group_id_field_name. */
1116 field_name = (uintptr_t)s->params.group_id_field_name;
1117 free((void *)field_name);
1118 s->params.group_id_field_name = NULL;
1120 /* params->selector_field_names. */
1121 for (i = 0; i < s->params.n_selector_fields; i++) {
1122 field_name = (uintptr_t)s->params.selector_field_names[i];
1124 free((void *)field_name);
1127 free(s->params.selector_field_names);
1128 s->params.selector_field_names = NULL;
1130 s->params.n_selector_fields = 0;
1132 /* params->member_id_field_name. */
1133 field_name = (uintptr_t)s->params.member_id_field_name;
1134 free((void *)field_name);
1135 s->params.member_id_field_name = NULL;
1137 /* params->n_groups_max. */
1138 s->params.n_groups_max = 0;
1140 /* params->n_members_per_group_max. */
1141 s->params.n_members_per_group_max = 0;
1145 selector_statement_parse(struct selector_spec *s,
1146 uint32_t *block_mask,
1151 const char **err_msg)
1154 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
1156 *err_line = n_lines;
1158 *err_msg = "Invalid selector statement.";
1163 s->name = strdup(tokens[1]);
1166 *err_line = n_lines;
1168 *err_msg = "Memory allocation failed.";
1173 *block_mask |= 1 << SELECTOR_BLOCK;
1179 selector_selector_statement_parse(uint32_t *block_mask,
1184 const char **err_msg)
1187 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1189 *err_line = n_lines;
1191 *err_msg = "Invalid selector statement.";
1196 *block_mask |= 1 << SELECTOR_SELECTOR_BLOCK;
1202 selector_selector_block_parse(struct selector_spec *s,
1203 uint32_t *block_mask,
1208 const char **err_msg)
1210 const char **new_fields;
1213 /* Handle end of block. */
1214 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1215 *block_mask &= ~(1 << SELECTOR_SELECTOR_BLOCK);
1219 /* Check input arguments. */
1220 if (n_tokens != 1) {
1222 *err_line = n_lines;
1224 *err_msg = "Invalid selector field statement.";
1228 name = strdup(tokens[0]);
1231 *err_line = n_lines;
1233 *err_msg = "Memory allocation failed.";
1237 new_fields = realloc(s->params.selector_field_names,
1238 (s->params.n_selector_fields + 1) * sizeof(char *));
1243 *err_line = n_lines;
1245 *err_msg = "Memory allocation failed.";
1249 s->params.selector_field_names = new_fields;
1250 s->params.selector_field_names[s->params.n_selector_fields] = name;
1251 s->params.n_selector_fields++;
1257 selector_block_parse(struct selector_spec *s,
1258 uint32_t *block_mask,
1263 const char **err_msg)
1265 if (*block_mask & (1 << SELECTOR_SELECTOR_BLOCK))
1266 return selector_selector_block_parse(s,
1274 /* Handle end of block. */
1275 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1276 *block_mask &= ~(1 << SELECTOR_BLOCK);
1280 if (!strcmp(tokens[0], "group_id")) {
1281 if (n_tokens != 2) {
1283 *err_line = n_lines;
1285 *err_msg = "Invalid group_id statement.";
1289 s->params.group_id_field_name = strdup(tokens[1]);
1290 if (!s->params.group_id_field_name) {
1292 *err_line = n_lines;
1294 *err_msg = "Memory allocation failed.";
1301 if (!strcmp(tokens[0], "selector"))
1302 return selector_selector_statement_parse(block_mask,
1309 if (!strcmp(tokens[0], "member_id")) {
1310 if (n_tokens != 2) {
1312 *err_line = n_lines;
1314 *err_msg = "Invalid member_id statement.";
1318 s->params.member_id_field_name = strdup(tokens[1]);
1319 if (!s->params.member_id_field_name) {
1321 *err_line = n_lines;
1323 *err_msg = "Memory allocation failed.";
1330 if (!strcmp(tokens[0], "n_groups_max")) {
1331 char *p = tokens[1];
1333 if (n_tokens != 2) {
1335 *err_line = n_lines;
1337 *err_msg = "Invalid n_groups statement.";
1341 s->params.n_groups_max = strtoul(p, &p, 0);
1344 *err_line = n_lines;
1346 *err_msg = "Invalid n_groups argument.";
1353 if (!strcmp(tokens[0], "n_members_per_group_max")) {
1354 char *p = tokens[1];
1356 if (n_tokens != 2) {
1358 *err_line = n_lines;
1360 *err_msg = "Invalid n_members_per_group statement.";
1364 s->params.n_members_per_group_max = strtoul(p, &p, 0);
1367 *err_line = n_lines;
1369 *err_msg = "Invalid n_members_per_group argument.";
1376 /* Anything else. */
1378 *err_line = n_lines;
1380 *err_msg = "Invalid statement.";
1387 * learner LEARNER_NAME {
1393 * ACTION_NAME [ @tableonly | @defaultonly]
1396 * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
1398 * timeout TIMEOUT_IN_SECONDS
1401 struct learner_spec {
1403 struct rte_swx_pipeline_learner_params params;
1409 learner_spec_free(struct learner_spec *s)
1411 uintptr_t default_action_name, default_action_args;
1420 for (i = 0; i < s->params.n_fields; i++) {
1421 uintptr_t name = (uintptr_t)s->params.field_names[i];
1426 free(s->params.field_names);
1427 s->params.field_names = NULL;
1429 s->params.n_fields = 0;
1431 for (i = 0; i < s->params.n_actions; i++) {
1432 uintptr_t name = (uintptr_t)s->params.action_names[i];
1437 free(s->params.action_names);
1438 s->params.action_names = NULL;
1440 s->params.n_actions = 0;
1442 default_action_name = (uintptr_t)s->params.default_action_name;
1443 free((void *)default_action_name);
1444 s->params.default_action_name = NULL;
1446 default_action_args = (uintptr_t)s->params.default_action_args;
1447 free((void *)default_action_args);
1448 s->params.default_action_args = NULL;
1450 free(s->params.action_is_for_table_entries);
1451 s->params.action_is_for_table_entries = NULL;
1453 free(s->params.action_is_for_default_entry);
1454 s->params.action_is_for_default_entry = NULL;
1456 s->params.default_action_is_const = 0;
1464 learner_key_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 key statement.";
1481 *block_mask |= 1 << LEARNER_KEY_BLOCK;
1487 learner_key_block_parse(struct learner_spec *s,
1488 uint32_t *block_mask,
1493 const char **err_msg)
1495 const char **new_field_names = NULL;
1496 char *field_name = NULL;
1498 /* Handle end of block. */
1499 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1500 *block_mask &= ~(1 << LEARNER_KEY_BLOCK);
1504 /* Check input arguments. */
1505 if (n_tokens != 1) {
1507 *err_line = n_lines;
1509 *err_msg = "Invalid match field statement.";
1513 field_name = strdup(tokens[0]);
1514 new_field_names = realloc(s->params.field_names, (s->params.n_fields + 1) * sizeof(char *));
1515 if (!field_name || !new_field_names) {
1517 free(new_field_names);
1520 *err_line = n_lines;
1522 *err_msg = "Memory allocation failed.";
1526 s->params.field_names = new_field_names;
1527 s->params.field_names[s->params.n_fields] = field_name;
1528 s->params.n_fields++;
1534 learner_actions_statement_parse(uint32_t *block_mask,
1539 const char **err_msg)
1542 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1544 *err_line = n_lines;
1546 *err_msg = "Invalid actions statement.";
1551 *block_mask |= 1 << LEARNER_ACTIONS_BLOCK;
1557 learner_actions_block_parse(struct learner_spec *s,
1558 uint32_t *block_mask,
1563 const char **err_msg)
1565 const char **new_action_names = NULL;
1566 int *new_action_is_for_table_entries = NULL, *new_action_is_for_default_entry = NULL;
1568 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
1570 /* Handle end of block. */
1571 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1572 *block_mask &= ~(1 << LEARNER_ACTIONS_BLOCK);
1576 /* Check input arguments. */
1577 if ((n_tokens > 2) ||
1578 ((n_tokens == 2) && strcmp(tokens[1], "@tableonly") &&
1579 strcmp(tokens[1], "@defaultonly"))) {
1581 *err_line = n_lines;
1583 *err_msg = "Invalid action name statement.";
1587 name = strdup(tokens[0]);
1589 if (n_tokens == 2) {
1590 if (!strcmp(tokens[1], "@tableonly"))
1591 action_is_for_default_entry = 0;
1593 if (!strcmp(tokens[1], "@defaultonly"))
1594 action_is_for_table_entries = 0;
1597 new_action_names = realloc(s->params.action_names,
1598 (s->params.n_actions + 1) * sizeof(char *));
1599 new_action_is_for_table_entries = realloc(s->params.action_is_for_table_entries,
1600 (s->params.n_actions + 1) * sizeof(int));
1601 new_action_is_for_default_entry = realloc(s->params.action_is_for_default_entry,
1602 (s->params.n_actions + 1) * sizeof(int));
1605 !new_action_names ||
1606 !new_action_is_for_table_entries ||
1607 !new_action_is_for_default_entry) {
1609 free(new_action_names);
1610 free(new_action_is_for_table_entries);
1611 free(new_action_is_for_default_entry);
1614 *err_line = n_lines;
1616 *err_msg = "Memory allocation failed.";
1620 s->params.action_names = new_action_names;
1621 s->params.action_names[s->params.n_actions] = name;
1623 s->params.action_is_for_table_entries = new_action_is_for_table_entries;
1624 s->params.action_is_for_table_entries[s->params.n_actions] = action_is_for_table_entries;
1626 s->params.action_is_for_default_entry = new_action_is_for_default_entry;
1627 s->params.action_is_for_default_entry[s->params.n_actions] = action_is_for_default_entry;
1629 s->params.n_actions++;
1635 learner_default_action_statement_parse(struct learner_spec *s,
1640 const char **err_msg)
1643 int status = 0, duplicate = 0;
1646 if ((n_tokens < 4) ||
1647 strcmp(tokens[2], "args")) {
1652 if (s->params.default_action_name) {
1658 s->params.default_action_name = strdup(tokens[1]);
1659 if (!s->params.default_action_name) {
1664 if (strcmp(tokens[3], "none")) {
1665 char buffer[MAX_LINE_LENGTH];
1666 uint32_t n_tokens_args = n_tokens - 3;
1668 if (!strcmp(tokens[n_tokens - 1], "const"))
1671 if (!n_tokens_args) {
1677 for (i = 0; i < n_tokens_args; i++) {
1679 strcat(buffer, " ");
1681 strcat(buffer, tokens[3 + i]);
1684 s->params.default_action_args = strdup(buffer);
1685 if (!s->params.default_action_args) {
1690 if (((n_tokens != 4) && (n_tokens != 5)) ||
1691 ((n_tokens == 5) && (strcmp(tokens[4], "const")))) {
1697 if (!strcmp(tokens[n_tokens - 1], "const"))
1698 s->params.default_action_is_const = 1;
1704 *err_line = n_lines;
1709 *err_msg = "Memory allocation failed.";
1714 *err_msg = "Duplicate default_action statement.";
1716 *err_msg = "Invalid default_action statement.";
1723 learner_statement_parse(struct learner_spec *s,
1724 uint32_t *block_mask,
1729 const char **err_msg)
1732 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
1734 *err_line = n_lines;
1736 *err_msg = "Invalid learner statement.";
1741 s->name = strdup(tokens[1]);
1744 *err_line = n_lines;
1746 *err_msg = "Memory allocation failed.";
1751 *block_mask |= 1 << LEARNER_BLOCK;
1757 learner_block_parse(struct learner_spec *s,
1758 uint32_t *block_mask,
1763 const char **err_msg)
1765 if (*block_mask & (1 << LEARNER_KEY_BLOCK))
1766 return learner_key_block_parse(s,
1774 if (*block_mask & (1 << LEARNER_ACTIONS_BLOCK))
1775 return learner_actions_block_parse(s,
1783 /* Handle end of block. */
1784 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1785 *block_mask &= ~(1 << LEARNER_BLOCK);
1789 if (!strcmp(tokens[0], "key"))
1790 return learner_key_statement_parse(block_mask,
1797 if (!strcmp(tokens[0], "actions"))
1798 return learner_actions_statement_parse(block_mask,
1805 if (!strcmp(tokens[0], "default_action"))
1806 return learner_default_action_statement_parse(s,
1813 if (!strcmp(tokens[0], "size")) {
1814 char *p = tokens[1];
1816 if (n_tokens != 2) {
1818 *err_line = n_lines;
1820 *err_msg = "Invalid size statement.";
1824 s->size = strtoul(p, &p, 0);
1827 *err_line = n_lines;
1829 *err_msg = "Invalid size argument.";
1836 if (!strcmp(tokens[0], "timeout")) {
1837 char *p = tokens[1];
1839 if (n_tokens != 2) {
1841 *err_line = n_lines;
1843 *err_msg = "Invalid timeout statement.";
1847 s->timeout = strtoul(p, &p, 0);
1850 *err_line = n_lines;
1852 *err_msg = "Invalid timeout argument.";
1859 /* Anything else. */
1861 *err_line = n_lines;
1863 *err_msg = "Invalid statement.";
1870 * regarray NAME size SIZE initval INITVAL
1872 struct regarray_spec {
1879 regarray_spec_free(struct regarray_spec *s)
1889 regarray_statement_parse(struct regarray_spec *s,
1894 const char **err_msg)
1899 if ((n_tokens != 6) ||
1900 strcmp(tokens[2], "size") ||
1901 strcmp(tokens[4], "initval")) {
1903 *err_line = n_lines;
1905 *err_msg = "Invalid regarray statement.";
1910 s->name = strdup(tokens[1]);
1913 *err_line = n_lines;
1915 *err_msg = "Memory allocation failed.";
1920 s->size = strtoul(p, &p, 0);
1921 if (p[0] || !s->size) {
1923 *err_line = n_lines;
1925 *err_msg = "Invalid size argument.";
1930 s->init_val = strtoull(p, &p, 0);
1933 *err_line = n_lines;
1935 *err_msg = "Invalid initval argument.";
1945 * metarray NAME size SIZE
1947 struct metarray_spec {
1953 metarray_spec_free(struct metarray_spec *s)
1963 metarray_statement_parse(struct metarray_spec *s,
1968 const char **err_msg)
1973 if ((n_tokens != 4) || strcmp(tokens[2], "size")) {
1975 *err_line = n_lines;
1977 *err_msg = "Invalid metarray statement.";
1982 s->name = strdup(tokens[1]);
1985 *err_line = n_lines;
1987 *err_msg = "Memory allocation failed.";
1992 s->size = strtoul(p, &p, 0);
1993 if (p[0] || !s->size) {
1995 *err_line = n_lines;
1997 *err_msg = "Invalid size argument.";
2013 const char **instructions;
2014 uint32_t n_instructions;
2018 apply_spec_free(struct apply_spec *s)
2025 for (i = 0; i < s->n_instructions; i++) {
2026 uintptr_t instr = (uintptr_t)s->instructions[i];
2028 free((void *)instr);
2031 free(s->instructions);
2032 s->instructions = NULL;
2034 s->n_instructions = 0;
2038 apply_statement_parse(uint32_t *block_mask,
2043 const char **err_msg)
2046 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
2048 *err_line = n_lines;
2050 *err_msg = "Invalid apply statement.";
2055 *block_mask |= 1 << APPLY_BLOCK;
2061 apply_block_parse(struct apply_spec *s,
2062 uint32_t *block_mask,
2067 const char **err_msg)
2069 char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr;
2070 const char **new_instructions;
2073 /* Handle end of block. */
2074 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
2075 *block_mask &= ~(1 << APPLY_BLOCK);
2081 for (i = 0; i < n_tokens; i++) {
2083 strcat(buffer, " ");
2084 strcat(buffer, tokens[i]);
2087 instr = strdup(buffer);
2090 *err_line = n_lines;
2092 *err_msg = "Memory allocation failed.";
2096 new_instructions = realloc(s->instructions,
2097 (s->n_instructions + 1) * sizeof(char *));
2098 if (!new_instructions) {
2102 *err_line = n_lines;
2104 *err_msg = "Memory allocation failed.";
2108 s->instructions = new_instructions;
2109 s->instructions[s->n_instructions] = instr;
2110 s->n_instructions++;
2119 rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
2122 const char **err_msg)
2124 struct extobj_spec extobj_spec = {0};
2125 struct struct_spec struct_spec = {0};
2126 struct header_spec header_spec = {0};
2127 struct metadata_spec metadata_spec = {0};
2128 struct action_spec action_spec = {0};
2129 struct table_spec table_spec = {0};
2130 struct selector_spec selector_spec = {0};
2131 struct learner_spec learner_spec = {0};
2132 struct regarray_spec regarray_spec = {0};
2133 struct metarray_spec metarray_spec = {0};
2134 struct apply_spec apply_spec = {0};
2136 uint32_t block_mask = 0;
2139 /* Check the input arguments. */
2144 *err_msg = "Null pipeline argument.";
2153 *err_msg = "Null specification file argument.";
2158 for (n_lines = 1; ; n_lines++) {
2159 char line[MAX_LINE_LENGTH];
2160 char *tokens[MAX_TOKENS], *ptr = line;
2161 uint32_t n_tokens = 0;
2163 /* Read next line. */
2164 if (!fgets(line, sizeof(line), spec))
2167 /* Parse the line into tokens. */
2172 token = strtok_r(ptr, " \f\n\r\t\v", &ptr);
2176 /* Handle comments. */
2177 if ((token[0] == '#') ||
2178 (token[0] == ';') ||
2179 ((token[0] == '/') && (token[1] == '/'))) {
2183 /* Handle excessively long lines. */
2184 if (n_tokens >= RTE_DIM(tokens)) {
2186 *err_line = n_lines;
2188 *err_msg = "Too many tokens.";
2193 /* Handle excessively long tokens. */
2194 if (strnlen(token, RTE_SWX_NAME_SIZE) >=
2195 RTE_SWX_NAME_SIZE) {
2197 *err_line = n_lines;
2199 *err_msg = "Token too big.";
2205 tokens[n_tokens] = token;
2209 /* Handle empty lines. */
2214 if (block_mask & (1 << STRUCT_BLOCK)) {
2215 status = struct_block_parse(&struct_spec,
2225 if (block_mask & (1 << STRUCT_BLOCK))
2229 status = rte_swx_pipeline_struct_type_register(p,
2232 struct_spec.n_fields,
2233 struct_spec.varbit);
2236 *err_line = n_lines;
2238 *err_msg = "Struct registration error.";
2242 struct_spec_free(&struct_spec);
2248 if (block_mask & (1 << ACTION_BLOCK)) {
2249 status = action_block_parse(&action_spec,
2259 if (block_mask & (1 << ACTION_BLOCK))
2263 status = rte_swx_pipeline_action_config(p,
2265 action_spec.args_struct_type_name,
2266 action_spec.instructions,
2267 action_spec.n_instructions);
2270 *err_line = n_lines;
2272 *err_msg = "Action config error.";
2276 action_spec_free(&action_spec);
2282 if (block_mask & (1 << TABLE_BLOCK)) {
2283 status = table_block_parse(&table_spec,
2293 if (block_mask & (1 << TABLE_BLOCK))
2297 status = rte_swx_pipeline_table_config(p,
2300 table_spec.recommended_table_type_name,
2305 *err_line = n_lines;
2307 *err_msg = "Table configuration error.";
2311 table_spec_free(&table_spec);
2316 /* selector block. */
2317 if (block_mask & (1 << SELECTOR_BLOCK)) {
2318 status = selector_block_parse(&selector_spec,
2328 if (block_mask & (1 << SELECTOR_BLOCK))
2332 status = rte_swx_pipeline_selector_config(p,
2334 &selector_spec.params);
2337 *err_line = n_lines;
2339 *err_msg = "Selector configuration error.";
2343 selector_spec_free(&selector_spec);
2348 /* learner block. */
2349 if (block_mask & (1 << LEARNER_BLOCK)) {
2350 status = learner_block_parse(&learner_spec,
2360 if (block_mask & (1 << LEARNER_BLOCK))
2364 status = rte_swx_pipeline_learner_config(p,
2366 &learner_spec.params,
2368 learner_spec.timeout);
2371 *err_line = n_lines;
2373 *err_msg = "Learner table configuration error.";
2377 learner_spec_free(&learner_spec);
2383 if (block_mask & (1 << APPLY_BLOCK)) {
2384 status = apply_block_parse(&apply_spec,
2394 if (block_mask & (1 << APPLY_BLOCK))
2398 status = rte_swx_pipeline_instructions_config(p,
2399 apply_spec.instructions,
2400 apply_spec.n_instructions);
2403 *err_line = n_lines;
2405 *err_msg = "Pipeline instructions err.";
2409 apply_spec_free(&apply_spec);
2415 if (!strcmp(tokens[0], "extobj")) {
2416 status = extobj_statement_parse(&extobj_spec,
2425 status = rte_swx_pipeline_extern_object_config(p,
2427 extobj_spec.extern_type_name,
2428 extobj_spec.pragma);
2431 *err_line = n_lines;
2433 *err_msg = "Extern object config err.";
2437 extobj_spec_free(&extobj_spec);
2443 if (!strcmp(tokens[0], "struct")) {
2444 status = struct_statement_parse(&struct_spec,
2458 if (!strcmp(tokens[0], "header")) {
2459 status = header_statement_parse(&header_spec,
2468 status = rte_swx_pipeline_packet_header_register(p,
2470 header_spec.struct_type_name);
2473 *err_line = n_lines;
2475 *err_msg = "Header registration error.";
2479 header_spec_free(&header_spec);
2485 if (!strcmp(tokens[0], "metadata")) {
2486 status = metadata_statement_parse(&metadata_spec,
2495 status = rte_swx_pipeline_packet_metadata_register(p,
2496 metadata_spec.struct_type_name);
2499 *err_line = n_lines;
2501 *err_msg = "Meta-data reg err.";
2505 metadata_spec_free(&metadata_spec);
2511 if (!strcmp(tokens[0], "action")) {
2512 status = action_statement_parse(&action_spec,
2526 if (!strcmp(tokens[0], "table")) {
2527 status = table_statement_parse(&table_spec,
2541 if (!strcmp(tokens[0], "selector")) {
2542 status = selector_statement_parse(&selector_spec,
2556 if (!strcmp(tokens[0], "learner")) {
2557 status = learner_statement_parse(&learner_spec,
2571 if (!strcmp(tokens[0], "regarray")) {
2572 status = regarray_statement_parse(®array_spec,
2581 status = rte_swx_pipeline_regarray_config(p,
2584 regarray_spec.init_val);
2587 *err_line = n_lines;
2589 *err_msg = "Register array configuration error.";
2593 regarray_spec_free(®array_spec);
2599 if (!strcmp(tokens[0], "metarray")) {
2600 status = metarray_statement_parse(&metarray_spec,
2609 status = rte_swx_pipeline_metarray_config(p,
2611 metarray_spec.size);
2614 *err_line = n_lines;
2616 *err_msg = "Meter array configuration error.";
2620 metarray_spec_free(&metarray_spec);
2626 if (!strcmp(tokens[0], "apply")) {
2627 status = apply_statement_parse(&block_mask,
2639 /* Anything else. */
2641 *err_line = n_lines;
2643 *err_msg = "Unknown statement.";
2648 /* Handle unfinished block. */
2651 *err_line = n_lines;
2653 *err_msg = "Missing }.";
2658 /* Pipeline build. */
2659 status = rte_swx_pipeline_build(p);
2662 *err_line = n_lines;
2664 *err_msg = "Pipeline build error.";
2671 extobj_spec_free(&extobj_spec);
2672 struct_spec_free(&struct_spec);
2673 header_spec_free(&header_spec);
2674 metadata_spec_free(&metadata_spec);
2675 action_spec_free(&action_spec);
2676 table_spec_free(&table_spec);
2677 selector_spec_free(&selector_spec);
2678 learner_spec_free(&learner_spec);
2679 regarray_spec_free(®array_spec);
2680 metarray_spec_free(&metarray_spec);
2681 apply_spec_free(&apply_spec);