1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2020 Intel Corporation
10 #include "rte_swx_pipeline.h"
11 #include "rte_swx_ctl.h"
13 #define MAX_LINE_LENGTH RTE_SWX_INSTRUCTION_SIZE
14 #define MAX_TOKENS RTE_SWX_INSTRUCTION_TOKENS_MAX
16 #define STRUCT_BLOCK 0
17 #define ACTION_BLOCK 1
19 #define TABLE_KEY_BLOCK 3
20 #define TABLE_ACTIONS_BLOCK 4
21 #define SELECTOR_BLOCK 5
22 #define SELECTOR_SELECTOR_BLOCK 6
23 #define LEARNER_BLOCK 7
24 #define LEARNER_KEY_BLOCK 8
25 #define LEARNER_ACTIONS_BLOCK 9
26 #define APPLY_BLOCK 10
31 * extobj OBJ_NAME instanceof OBJ_TYPE [ pragma OBJ_CREATE_ARGS ]
35 char *extern_type_name;
40 extobj_spec_free(struct extobj_spec *s)
48 free(s->extern_type_name);
49 s->extern_type_name = NULL;
56 extobj_statement_parse(struct extobj_spec *s,
64 if (((n_tokens != 4) && (n_tokens != 6)) ||
65 ((n_tokens == 4) && strcmp(tokens[2], "instanceof")) ||
66 ((n_tokens == 6) && (strcmp(tokens[2], "instanceof") ||
67 strcmp(tokens[4], "pragma")))) {
71 *err_msg = "Invalid extobj statement.";
76 s->name = strdup(tokens[1]);
77 s->extern_type_name = strdup(tokens[3]);
78 s->pragma = (n_tokens == 6) ? strdup(tokens[5]) : NULL;
81 !s->extern_type_name ||
82 ((n_tokens == 6) && !s->pragma)) {
84 free(s->extern_type_name);
90 *err_msg = "Memory allocation failed.";
100 * struct STRUCT_TYPE_NAME {
101 * bit<SIZE> | varbit<SIZE> FIELD_NAME
107 struct rte_swx_field_params *fields;
113 struct_spec_free(struct struct_spec *s)
123 for (i = 0; i < s->n_fields; i++) {
124 uintptr_t name = (uintptr_t)s->fields[i].name;
138 struct_statement_parse(struct struct_spec *s,
139 uint32_t *block_mask,
144 const char **err_msg)
147 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
151 *err_msg = "Invalid struct statement.";
156 s->name = strdup(tokens[1]);
161 *err_msg = "Memory allocation failed.";
166 *block_mask |= 1 << STRUCT_BLOCK;
172 struct_block_parse(struct struct_spec *s,
173 uint32_t *block_mask,
178 const char **err_msg)
180 struct rte_swx_field_params *new_fields;
181 char *p = tokens[0], *name = NULL;
183 int varbit = 0, error = 0, error_size_invalid = 0, error_varbit_not_last = 0;
185 /* Handle end of block. */
186 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
187 *block_mask &= ~(1 << STRUCT_BLOCK);
199 error_varbit_not_last = 1;
203 if (!strncmp(p, "bit<", strlen("bit<"))) {
204 size_t len = strlen(p);
206 if ((len < strlen("bit< >")) || (p[len - 1] != '>')) {
211 /* Remove the "bit<" and ">". */
212 p[strlen(p) - 1] = 0;
214 } else if (!strncmp(p, "varbit<", strlen("varbit<"))) {
215 size_t len = strlen(p);
217 if ((len < strlen("varbit< >")) || (p[len - 1] != '>')) {
222 /* Remove the "varbit<" and ">". */
223 p[strlen(p) - 1] = 0;
224 p += strlen("varbit<");
226 /* Set the varbit flag. */
233 n_bits = strtoul(p, &p, 0);
237 ((n_bits > 64) && !varbit)) {
239 error_size_invalid = 1;
244 name = strdup(tokens[1]);
250 new_fields = realloc(s->fields, (s->n_fields + 1) * sizeof(struct rte_swx_field_params));
256 s->fields = new_fields;
257 s->fields[s->n_fields].name = name;
258 s->fields[s->n_fields].n_bits = n_bits;
271 *err_msg = "Invalid struct field statement.";
273 if ((error == -EINVAL) && error_varbit_not_last)
274 *err_msg = "Varbit field is not the last struct field.";
276 if ((error == -EINVAL) && error_size_invalid)
277 *err_msg = "Invalid struct field size.";
279 if (error == -ENOMEM)
280 *err_msg = "Memory allocation failed.";
289 * header HEADER_NAME instanceof STRUCT_TYPE_NAME
293 char *struct_type_name;
297 header_spec_free(struct header_spec *s)
305 free(s->struct_type_name);
306 s->struct_type_name = NULL;
310 header_statement_parse(struct header_spec *s,
315 const char **err_msg)
318 if ((n_tokens != 4) || strcmp(tokens[2], "instanceof")) {
322 *err_msg = "Invalid header statement.";
327 s->name = strdup(tokens[1]);
328 s->struct_type_name = strdup(tokens[3]);
330 if (!s->name || !s->struct_type_name) {
332 free(s->struct_type_name);
337 *err_msg = "Memory allocation failed.";
347 * metadata instanceof STRUCT_TYPE_NAME
349 struct metadata_spec {
350 char *struct_type_name;
354 metadata_spec_free(struct metadata_spec *s)
359 free(s->struct_type_name);
360 s->struct_type_name = NULL;
364 metadata_statement_parse(struct metadata_spec *s,
369 const char **err_msg)
372 if ((n_tokens != 3) || strcmp(tokens[1], "instanceof")) {
376 *err_msg = "Invalid metadata statement.";
381 s->struct_type_name = strdup(tokens[2]);
382 if (!s->struct_type_name) {
386 *err_msg = "Memory allocation failed.";
396 * action ACTION_NAME args none | instanceof STRUCT_TYPE_NAME {
403 char *args_struct_type_name;
404 const char **instructions;
405 uint32_t n_instructions;
409 action_spec_free(struct action_spec *s)
419 free(s->args_struct_type_name);
420 s->args_struct_type_name = NULL;
422 for (i = 0; i < s->n_instructions; i++) {
423 uintptr_t instr = (uintptr_t)s->instructions[i];
428 free(s->instructions);
429 s->instructions = NULL;
431 s->n_instructions = 0;
435 action_statement_parse(struct action_spec *s,
436 uint32_t *block_mask,
441 const char **err_msg)
444 if (((n_tokens != 5) && (n_tokens != 6)) ||
446 (strcmp(tokens[2], "args") ||
447 strcmp(tokens[3], "none") ||
448 strcmp(tokens[4], "{"))) ||
450 (strcmp(tokens[2], "args") ||
451 strcmp(tokens[3], "instanceof") ||
452 strcmp(tokens[5], "{")))) {
456 *err_msg = "Invalid action statement.";
461 s->name = strdup(tokens[1]);
462 s->args_struct_type_name = (n_tokens == 6) ? strdup(tokens[4]) : NULL;
464 if ((!s->name) || ((n_tokens == 6) && !s->args_struct_type_name)) {
468 *err_msg = "Memory allocation failed.";
473 *block_mask |= 1 << ACTION_BLOCK;
479 action_block_parse(struct action_spec *s,
480 uint32_t *block_mask,
485 const char **err_msg)
487 char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr;
488 const char **new_instructions;
491 /* Handle end of block. */
492 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
493 *block_mask &= ~(1 << ACTION_BLOCK);
499 for (i = 0; i < n_tokens; i++) {
502 strcat(buffer, tokens[i]);
505 instr = strdup(buffer);
510 *err_msg = "Memory allocation failed.";
514 new_instructions = realloc(s->instructions,
515 (s->n_instructions + 1) * sizeof(char *));
516 if (!new_instructions) {
522 *err_msg = "Memory allocation failed.";
526 s->instructions = new_instructions;
527 s->instructions[s->n_instructions] = instr;
538 * MATCH_FIELD_NAME exact | wildcard | lpm
542 * ACTION_NAME [ @tableonly | @defaultonly ]
545 * default_action ACTION_NAME args none | ARGS_BYTE_ARRAY [ const ]
546 * instanceof TABLE_TYPE_NAME
553 struct rte_swx_pipeline_table_params params;
554 char *recommended_table_type_name;
560 table_spec_free(struct table_spec *s)
562 uintptr_t default_action_name;
571 for (i = 0; i < s->params.n_fields; i++) {
572 uintptr_t name = (uintptr_t)s->params.fields[i].name;
577 free(s->params.fields);
578 s->params.fields = NULL;
580 s->params.n_fields = 0;
582 for (i = 0; i < s->params.n_actions; i++) {
583 uintptr_t name = (uintptr_t)s->params.action_names[i];
588 free(s->params.action_names);
589 s->params.action_names = NULL;
591 s->params.n_actions = 0;
593 default_action_name = (uintptr_t)s->params.default_action_name;
594 free((void *)default_action_name);
595 s->params.default_action_name = NULL;
597 free(s->params.default_action_data);
598 s->params.default_action_data = NULL;
600 free(s->params.action_is_for_table_entries);
601 s->params.action_is_for_table_entries = NULL;
603 free(s->params.action_is_for_default_entry);
604 s->params.action_is_for_default_entry = NULL;
606 s->params.default_action_is_const = 0;
608 free(s->recommended_table_type_name);
609 s->recommended_table_type_name = NULL;
618 table_key_statement_parse(uint32_t *block_mask,
623 const char **err_msg)
626 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
630 *err_msg = "Invalid key statement.";
635 *block_mask |= 1 << TABLE_KEY_BLOCK;
641 table_key_block_parse(struct table_spec *s,
642 uint32_t *block_mask,
647 const char **err_msg)
649 struct rte_swx_match_field_params *new_fields;
650 enum rte_swx_table_match_type match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
653 /* Handle end of block. */
654 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
655 *block_mask &= ~(1 << TABLE_KEY_BLOCK);
659 /* Check input arguments. */
660 if ((n_tokens != 2) ||
661 (strcmp(tokens[1], "exact") &&
662 strcmp(tokens[1], "wildcard") &&
663 strcmp(tokens[1], "lpm"))) {
667 *err_msg = "Invalid match field statement.";
671 if (!strcmp(tokens[1], "wildcard"))
672 match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
673 if (!strcmp(tokens[1], "lpm"))
674 match_type = RTE_SWX_TABLE_MATCH_LPM;
675 if (!strcmp(tokens[1], "exact"))
676 match_type = RTE_SWX_TABLE_MATCH_EXACT;
678 name = strdup(tokens[0]);
683 *err_msg = "Memory allocation failed.";
687 new_fields = realloc(s->params.fields,
688 (s->params.n_fields + 1) * sizeof(struct rte_swx_match_field_params));
695 *err_msg = "Memory allocation failed.";
699 s->params.fields = new_fields;
700 s->params.fields[s->params.n_fields].name = name;
701 s->params.fields[s->params.n_fields].match_type = match_type;
702 s->params.n_fields++;
708 table_actions_statement_parse(uint32_t *block_mask,
713 const char **err_msg)
716 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
720 *err_msg = "Invalid actions statement.";
725 *block_mask |= 1 << TABLE_ACTIONS_BLOCK;
731 table_actions_block_parse(struct table_spec *s,
732 uint32_t *block_mask,
737 const char **err_msg)
739 const char **new_action_names = NULL;
740 int *new_action_is_for_table_entries = NULL, *new_action_is_for_default_entry = NULL;
742 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
744 /* Handle end of block. */
745 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
746 *block_mask &= ~(1 << TABLE_ACTIONS_BLOCK);
750 /* Check input arguments. */
751 if ((n_tokens > 2) ||
752 ((n_tokens == 2) && strcmp(tokens[1], "@tableonly") &&
753 strcmp(tokens[1], "@defaultonly"))) {
757 *err_msg = "Invalid action name statement.";
761 name = strdup(tokens[0]);
764 if (!strcmp(tokens[1], "@tableonly"))
765 action_is_for_default_entry = 0;
767 if (!strcmp(tokens[1], "@defaultonly"))
768 action_is_for_table_entries = 0;
771 new_action_names = realloc(s->params.action_names,
772 (s->params.n_actions + 1) * sizeof(char *));
773 new_action_is_for_table_entries = realloc(s->params.action_is_for_table_entries,
774 (s->params.n_actions + 1) * sizeof(int));
775 new_action_is_for_default_entry = realloc(s->params.action_is_for_default_entry,
776 (s->params.n_actions + 1) * sizeof(int));
780 !new_action_is_for_table_entries ||
781 !new_action_is_for_default_entry) {
783 free(new_action_names);
784 free(new_action_is_for_table_entries);
785 free(new_action_is_for_default_entry);
790 *err_msg = "Memory allocation failed.";
794 s->params.action_names = new_action_names;
795 s->params.action_names[s->params.n_actions] = name;
797 s->params.action_is_for_table_entries = new_action_is_for_table_entries;
798 s->params.action_is_for_table_entries[s->params.n_actions] = action_is_for_table_entries;
800 s->params.action_is_for_default_entry = new_action_is_for_default_entry;
801 s->params.action_is_for_default_entry[s->params.n_actions] = action_is_for_default_entry;
803 s->params.n_actions++;
809 table_statement_parse(struct table_spec *s,
810 uint32_t *block_mask,
815 const char **err_msg)
818 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
822 *err_msg = "Invalid table statement.";
827 s->name = strdup(tokens[1]);
832 *err_msg = "Memory allocation failed.";
837 *block_mask |= 1 << TABLE_BLOCK;
843 table_block_parse(struct table_spec *s,
844 uint32_t *block_mask,
849 const char **err_msg)
851 if (*block_mask & (1 << TABLE_KEY_BLOCK))
852 return table_key_block_parse(s,
860 if (*block_mask & (1 << TABLE_ACTIONS_BLOCK))
861 return table_actions_block_parse(s,
869 /* Handle end of block. */
870 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
871 *block_mask &= ~(1 << TABLE_BLOCK);
875 if (!strcmp(tokens[0], "key"))
876 return table_key_statement_parse(block_mask,
883 if (!strcmp(tokens[0], "actions"))
884 return table_actions_statement_parse(block_mask,
891 if (!strcmp(tokens[0], "default_action")) {
892 if (((n_tokens != 4) && (n_tokens != 5)) ||
893 strcmp(tokens[2], "args") ||
894 strcmp(tokens[3], "none") ||
895 ((n_tokens == 5) && strcmp(tokens[4], "const"))) {
899 *err_msg = "Invalid default_action statement.";
903 if (s->params.default_action_name) {
907 *err_msg = "Duplicate default_action stmt.";
911 s->params.default_action_name = strdup(tokens[1]);
912 if (!s->params.default_action_name) {
916 *err_msg = "Memory allocation failed.";
921 s->params.default_action_is_const = 1;
926 if (!strcmp(tokens[0], "instanceof")) {
931 *err_msg = "Invalid instanceof statement.";
935 if (s->recommended_table_type_name) {
939 *err_msg = "Duplicate instanceof statement.";
943 s->recommended_table_type_name = strdup(tokens[1]);
944 if (!s->recommended_table_type_name) {
948 *err_msg = "Memory allocation failed.";
955 if (!strcmp(tokens[0], "pragma")) {
960 *err_msg = "Invalid pragma statement.";
968 *err_msg = "Duplicate pragma statement.";
972 s->args = strdup(tokens[1]);
977 *err_msg = "Memory allocation failed.";
984 if (!strcmp(tokens[0], "size")) {
991 *err_msg = "Invalid pragma statement.";
995 s->size = strtoul(p, &p, 0);
1000 *err_msg = "Invalid size argument.";
1007 /* Anything else. */
1009 *err_line = n_lines;
1011 *err_msg = "Invalid statement.";
1018 * selector SELECTOR_NAME {
1019 * group_id FIELD_NAME
1024 * member_id FIELD_NAME
1026 * n_members_per_group N_MEMBERS_PER_GROUP
1029 struct selector_spec {
1031 struct rte_swx_pipeline_selector_params params;
1035 selector_spec_free(struct selector_spec *s)
1037 uintptr_t field_name;
1047 /* params->group_id_field_name. */
1048 field_name = (uintptr_t)s->params.group_id_field_name;
1049 free((void *)field_name);
1050 s->params.group_id_field_name = NULL;
1052 /* params->selector_field_names. */
1053 for (i = 0; i < s->params.n_selector_fields; i++) {
1054 field_name = (uintptr_t)s->params.selector_field_names[i];
1056 free((void *)field_name);
1059 free(s->params.selector_field_names);
1060 s->params.selector_field_names = NULL;
1062 s->params.n_selector_fields = 0;
1064 /* params->member_id_field_name. */
1065 field_name = (uintptr_t)s->params.member_id_field_name;
1066 free((void *)field_name);
1067 s->params.member_id_field_name = NULL;
1069 /* params->n_groups_max. */
1070 s->params.n_groups_max = 0;
1072 /* params->n_members_per_group_max. */
1073 s->params.n_members_per_group_max = 0;
1077 selector_statement_parse(struct selector_spec *s,
1078 uint32_t *block_mask,
1083 const char **err_msg)
1086 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
1088 *err_line = n_lines;
1090 *err_msg = "Invalid selector statement.";
1095 s->name = strdup(tokens[1]);
1098 *err_line = n_lines;
1100 *err_msg = "Memory allocation failed.";
1105 *block_mask |= 1 << SELECTOR_BLOCK;
1111 selector_selector_statement_parse(uint32_t *block_mask,
1116 const char **err_msg)
1119 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1121 *err_line = n_lines;
1123 *err_msg = "Invalid selector statement.";
1128 *block_mask |= 1 << SELECTOR_SELECTOR_BLOCK;
1134 selector_selector_block_parse(struct selector_spec *s,
1135 uint32_t *block_mask,
1140 const char **err_msg)
1142 const char **new_fields;
1145 /* Handle end of block. */
1146 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1147 *block_mask &= ~(1 << SELECTOR_SELECTOR_BLOCK);
1151 /* Check input arguments. */
1152 if (n_tokens != 1) {
1154 *err_line = n_lines;
1156 *err_msg = "Invalid selector field statement.";
1160 name = strdup(tokens[0]);
1163 *err_line = n_lines;
1165 *err_msg = "Memory allocation failed.";
1169 new_fields = realloc(s->params.selector_field_names,
1170 (s->params.n_selector_fields + 1) * sizeof(char *));
1175 *err_line = n_lines;
1177 *err_msg = "Memory allocation failed.";
1181 s->params.selector_field_names = new_fields;
1182 s->params.selector_field_names[s->params.n_selector_fields] = name;
1183 s->params.n_selector_fields++;
1189 selector_block_parse(struct selector_spec *s,
1190 uint32_t *block_mask,
1195 const char **err_msg)
1197 if (*block_mask & (1 << SELECTOR_SELECTOR_BLOCK))
1198 return selector_selector_block_parse(s,
1206 /* Handle end of block. */
1207 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1208 *block_mask &= ~(1 << SELECTOR_BLOCK);
1212 if (!strcmp(tokens[0], "group_id")) {
1213 if (n_tokens != 2) {
1215 *err_line = n_lines;
1217 *err_msg = "Invalid group_id statement.";
1221 s->params.group_id_field_name = strdup(tokens[1]);
1222 if (!s->params.group_id_field_name) {
1224 *err_line = n_lines;
1226 *err_msg = "Memory allocation failed.";
1233 if (!strcmp(tokens[0], "selector"))
1234 return selector_selector_statement_parse(block_mask,
1241 if (!strcmp(tokens[0], "member_id")) {
1242 if (n_tokens != 2) {
1244 *err_line = n_lines;
1246 *err_msg = "Invalid member_id statement.";
1250 s->params.member_id_field_name = strdup(tokens[1]);
1251 if (!s->params.member_id_field_name) {
1253 *err_line = n_lines;
1255 *err_msg = "Memory allocation failed.";
1262 if (!strcmp(tokens[0], "n_groups_max")) {
1263 char *p = tokens[1];
1265 if (n_tokens != 2) {
1267 *err_line = n_lines;
1269 *err_msg = "Invalid n_groups statement.";
1273 s->params.n_groups_max = strtoul(p, &p, 0);
1276 *err_line = n_lines;
1278 *err_msg = "Invalid n_groups argument.";
1285 if (!strcmp(tokens[0], "n_members_per_group_max")) {
1286 char *p = tokens[1];
1288 if (n_tokens != 2) {
1290 *err_line = n_lines;
1292 *err_msg = "Invalid n_members_per_group statement.";
1296 s->params.n_members_per_group_max = strtoul(p, &p, 0);
1299 *err_line = n_lines;
1301 *err_msg = "Invalid n_members_per_group argument.";
1308 /* Anything else. */
1310 *err_line = n_lines;
1312 *err_msg = "Invalid statement.";
1325 * ACTION_NAME [ @tableonly | @defaultonly]
1328 * default_action ACTION_NAME args none | ARGS_BYTE_ARRAY [ const ]
1330 * timeout TIMEOUT_IN_SECONDS
1333 struct learner_spec {
1335 struct rte_swx_pipeline_learner_params params;
1341 learner_spec_free(struct learner_spec *s)
1343 uintptr_t default_action_name;
1352 for (i = 0; i < s->params.n_fields; i++) {
1353 uintptr_t name = (uintptr_t)s->params.field_names[i];
1358 free(s->params.field_names);
1359 s->params.field_names = NULL;
1361 s->params.n_fields = 0;
1363 for (i = 0; i < s->params.n_actions; i++) {
1364 uintptr_t name = (uintptr_t)s->params.action_names[i];
1369 free(s->params.action_names);
1370 s->params.action_names = NULL;
1372 s->params.n_actions = 0;
1374 default_action_name = (uintptr_t)s->params.default_action_name;
1375 free((void *)default_action_name);
1376 s->params.default_action_name = NULL;
1378 free(s->params.default_action_data);
1379 s->params.default_action_data = NULL;
1381 free(s->params.action_is_for_table_entries);
1382 s->params.action_is_for_table_entries = NULL;
1384 free(s->params.action_is_for_default_entry);
1385 s->params.action_is_for_default_entry = NULL;
1387 s->params.default_action_is_const = 0;
1395 learner_key_statement_parse(uint32_t *block_mask,
1400 const char **err_msg)
1403 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1405 *err_line = n_lines;
1407 *err_msg = "Invalid key statement.";
1412 *block_mask |= 1 << LEARNER_KEY_BLOCK;
1418 learner_key_block_parse(struct learner_spec *s,
1419 uint32_t *block_mask,
1424 const char **err_msg)
1426 const char **new_field_names = NULL;
1427 char *field_name = NULL;
1429 /* Handle end of block. */
1430 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1431 *block_mask &= ~(1 << LEARNER_KEY_BLOCK);
1435 /* Check input arguments. */
1436 if (n_tokens != 1) {
1438 *err_line = n_lines;
1440 *err_msg = "Invalid match field statement.";
1444 field_name = strdup(tokens[0]);
1445 new_field_names = realloc(s->params.field_names, (s->params.n_fields + 1) * sizeof(char *));
1446 if (!field_name || !new_field_names) {
1448 free(new_field_names);
1451 *err_line = n_lines;
1453 *err_msg = "Memory allocation failed.";
1457 s->params.field_names = new_field_names;
1458 s->params.field_names[s->params.n_fields] = field_name;
1459 s->params.n_fields++;
1465 learner_actions_statement_parse(uint32_t *block_mask,
1470 const char **err_msg)
1473 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1475 *err_line = n_lines;
1477 *err_msg = "Invalid actions statement.";
1482 *block_mask |= 1 << LEARNER_ACTIONS_BLOCK;
1488 learner_actions_block_parse(struct learner_spec *s,
1489 uint32_t *block_mask,
1494 const char **err_msg)
1496 const char **new_action_names = NULL;
1497 int *new_action_is_for_table_entries = NULL, *new_action_is_for_default_entry = NULL;
1499 int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
1501 /* Handle end of block. */
1502 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1503 *block_mask &= ~(1 << LEARNER_ACTIONS_BLOCK);
1507 /* Check input arguments. */
1508 if ((n_tokens > 2) ||
1509 ((n_tokens == 2) && strcmp(tokens[1], "@tableonly") &&
1510 strcmp(tokens[1], "@defaultonly"))) {
1512 *err_line = n_lines;
1514 *err_msg = "Invalid action name statement.";
1518 name = strdup(tokens[0]);
1520 if (n_tokens == 2) {
1521 if (!strcmp(tokens[1], "@tableonly"))
1522 action_is_for_default_entry = 0;
1524 if (!strcmp(tokens[1], "@defaultonly"))
1525 action_is_for_table_entries = 0;
1528 new_action_names = realloc(s->params.action_names,
1529 (s->params.n_actions + 1) * sizeof(char *));
1530 new_action_is_for_table_entries = realloc(s->params.action_is_for_table_entries,
1531 (s->params.n_actions + 1) * sizeof(int));
1532 new_action_is_for_default_entry = realloc(s->params.action_is_for_default_entry,
1533 (s->params.n_actions + 1) * sizeof(int));
1536 !new_action_names ||
1537 !new_action_is_for_table_entries ||
1538 !new_action_is_for_default_entry) {
1540 free(new_action_names);
1541 free(new_action_is_for_table_entries);
1542 free(new_action_is_for_default_entry);
1545 *err_line = n_lines;
1547 *err_msg = "Memory allocation failed.";
1551 s->params.action_names = new_action_names;
1552 s->params.action_names[s->params.n_actions] = name;
1554 s->params.action_is_for_table_entries = new_action_is_for_table_entries;
1555 s->params.action_is_for_table_entries[s->params.n_actions] = action_is_for_table_entries;
1557 s->params.action_is_for_default_entry = new_action_is_for_default_entry;
1558 s->params.action_is_for_default_entry[s->params.n_actions] = action_is_for_default_entry;
1560 s->params.n_actions++;
1566 learner_statement_parse(struct learner_spec *s,
1567 uint32_t *block_mask,
1572 const char **err_msg)
1575 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
1577 *err_line = n_lines;
1579 *err_msg = "Invalid learner statement.";
1584 s->name = strdup(tokens[1]);
1587 *err_line = n_lines;
1589 *err_msg = "Memory allocation failed.";
1594 *block_mask |= 1 << LEARNER_BLOCK;
1600 learner_block_parse(struct learner_spec *s,
1601 uint32_t *block_mask,
1606 const char **err_msg)
1608 if (*block_mask & (1 << LEARNER_KEY_BLOCK))
1609 return learner_key_block_parse(s,
1617 if (*block_mask & (1 << LEARNER_ACTIONS_BLOCK))
1618 return learner_actions_block_parse(s,
1626 /* Handle end of block. */
1627 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1628 *block_mask &= ~(1 << LEARNER_BLOCK);
1632 if (!strcmp(tokens[0], "key"))
1633 return learner_key_statement_parse(block_mask,
1640 if (!strcmp(tokens[0], "actions"))
1641 return learner_actions_statement_parse(block_mask,
1648 if (!strcmp(tokens[0], "default_action")) {
1649 if (((n_tokens != 4) && (n_tokens != 5)) ||
1650 strcmp(tokens[2], "args") ||
1651 strcmp(tokens[3], "none") ||
1652 ((n_tokens == 5) && strcmp(tokens[4], "const"))) {
1654 *err_line = n_lines;
1656 *err_msg = "Invalid default_action statement.";
1660 if (s->params.default_action_name) {
1662 *err_line = n_lines;
1664 *err_msg = "Duplicate default_action stmt.";
1668 s->params.default_action_name = strdup(tokens[1]);
1669 if (!s->params.default_action_name) {
1671 *err_line = n_lines;
1673 *err_msg = "Memory allocation failed.";
1678 s->params.default_action_is_const = 1;
1683 if (!strcmp(tokens[0], "size")) {
1684 char *p = tokens[1];
1686 if (n_tokens != 2) {
1688 *err_line = n_lines;
1690 *err_msg = "Invalid size statement.";
1694 s->size = strtoul(p, &p, 0);
1697 *err_line = n_lines;
1699 *err_msg = "Invalid size argument.";
1706 if (!strcmp(tokens[0], "timeout")) {
1707 char *p = tokens[1];
1709 if (n_tokens != 2) {
1711 *err_line = n_lines;
1713 *err_msg = "Invalid timeout statement.";
1717 s->timeout = strtoul(p, &p, 0);
1720 *err_line = n_lines;
1722 *err_msg = "Invalid timeout argument.";
1729 /* Anything else. */
1731 *err_line = n_lines;
1733 *err_msg = "Invalid statement.";
1740 * regarray NAME size SIZE initval INITVAL
1742 struct regarray_spec {
1749 regarray_spec_free(struct regarray_spec *s)
1759 regarray_statement_parse(struct regarray_spec *s,
1764 const char **err_msg)
1769 if ((n_tokens != 6) ||
1770 strcmp(tokens[2], "size") ||
1771 strcmp(tokens[4], "initval")) {
1773 *err_line = n_lines;
1775 *err_msg = "Invalid regarray statement.";
1780 s->name = strdup(tokens[1]);
1783 *err_line = n_lines;
1785 *err_msg = "Memory allocation failed.";
1790 s->size = strtoul(p, &p, 0);
1791 if (p[0] || !s->size) {
1793 *err_line = n_lines;
1795 *err_msg = "Invalid size argument.";
1800 s->init_val = strtoull(p, &p, 0);
1803 *err_line = n_lines;
1805 *err_msg = "Invalid initval argument.";
1815 * metarray NAME size SIZE
1817 struct metarray_spec {
1823 metarray_spec_free(struct metarray_spec *s)
1833 metarray_statement_parse(struct metarray_spec *s,
1838 const char **err_msg)
1843 if ((n_tokens != 4) || strcmp(tokens[2], "size")) {
1845 *err_line = n_lines;
1847 *err_msg = "Invalid metarray statement.";
1852 s->name = strdup(tokens[1]);
1855 *err_line = n_lines;
1857 *err_msg = "Memory allocation failed.";
1862 s->size = strtoul(p, &p, 0);
1863 if (p[0] || !s->size) {
1865 *err_line = n_lines;
1867 *err_msg = "Invalid size argument.";
1883 const char **instructions;
1884 uint32_t n_instructions;
1888 apply_spec_free(struct apply_spec *s)
1895 for (i = 0; i < s->n_instructions; i++) {
1896 uintptr_t instr = (uintptr_t)s->instructions[i];
1898 free((void *)instr);
1901 free(s->instructions);
1902 s->instructions = NULL;
1904 s->n_instructions = 0;
1908 apply_statement_parse(uint32_t *block_mask,
1913 const char **err_msg)
1916 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1918 *err_line = n_lines;
1920 *err_msg = "Invalid apply statement.";
1925 *block_mask |= 1 << APPLY_BLOCK;
1931 apply_block_parse(struct apply_spec *s,
1932 uint32_t *block_mask,
1937 const char **err_msg)
1939 char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr;
1940 const char **new_instructions;
1943 /* Handle end of block. */
1944 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1945 *block_mask &= ~(1 << APPLY_BLOCK);
1951 for (i = 0; i < n_tokens; i++) {
1953 strcat(buffer, " ");
1954 strcat(buffer, tokens[i]);
1957 instr = strdup(buffer);
1960 *err_line = n_lines;
1962 *err_msg = "Memory allocation failed.";
1966 new_instructions = realloc(s->instructions,
1967 (s->n_instructions + 1) * sizeof(char *));
1968 if (!new_instructions) {
1972 *err_line = n_lines;
1974 *err_msg = "Memory allocation failed.";
1978 s->instructions = new_instructions;
1979 s->instructions[s->n_instructions] = instr;
1980 s->n_instructions++;
1989 rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
1992 const char **err_msg)
1994 struct extobj_spec extobj_spec = {0};
1995 struct struct_spec struct_spec = {0};
1996 struct header_spec header_spec = {0};
1997 struct metadata_spec metadata_spec = {0};
1998 struct action_spec action_spec = {0};
1999 struct table_spec table_spec = {0};
2000 struct selector_spec selector_spec = {0};
2001 struct learner_spec learner_spec = {0};
2002 struct regarray_spec regarray_spec = {0};
2003 struct metarray_spec metarray_spec = {0};
2004 struct apply_spec apply_spec = {0};
2006 uint32_t block_mask = 0;
2009 /* Check the input arguments. */
2014 *err_msg = "Null pipeline arument.";
2023 *err_msg = "Null specification file argument.";
2028 for (n_lines = 1; ; n_lines++) {
2029 char line[MAX_LINE_LENGTH];
2030 char *tokens[MAX_TOKENS], *ptr = line;
2031 uint32_t n_tokens = 0;
2033 /* Read next line. */
2034 if (!fgets(line, sizeof(line), spec))
2037 /* Parse the line into tokens. */
2042 token = strtok_r(ptr, " \f\n\r\t\v", &ptr);
2046 /* Handle comments. */
2047 if ((token[0] == '#') ||
2048 (token[0] == ';') ||
2049 ((token[0] == '/') && (token[1] == '/'))) {
2053 /* Handle excessively long lines. */
2054 if (n_tokens >= MAX_TOKENS) {
2056 *err_line = n_lines;
2058 *err_msg = "Too many tokens.";
2063 /* Handle excessively long tokens. */
2064 if (strnlen(token, RTE_SWX_NAME_SIZE) >=
2065 RTE_SWX_NAME_SIZE) {
2067 *err_line = n_lines;
2069 *err_msg = "Token too big.";
2075 tokens[n_tokens] = token;
2079 /* Handle empty lines. */
2084 if (block_mask & (1 << STRUCT_BLOCK)) {
2085 status = struct_block_parse(&struct_spec,
2095 if (block_mask & (1 << STRUCT_BLOCK))
2099 status = rte_swx_pipeline_struct_type_register(p,
2102 struct_spec.n_fields,
2103 struct_spec.varbit);
2106 *err_line = n_lines;
2108 *err_msg = "Struct registration error.";
2112 struct_spec_free(&struct_spec);
2118 if (block_mask & (1 << ACTION_BLOCK)) {
2119 status = action_block_parse(&action_spec,
2129 if (block_mask & (1 << ACTION_BLOCK))
2133 status = rte_swx_pipeline_action_config(p,
2135 action_spec.args_struct_type_name,
2136 action_spec.instructions,
2137 action_spec.n_instructions);
2140 *err_line = n_lines;
2142 *err_msg = "Action config error.";
2146 action_spec_free(&action_spec);
2152 if (block_mask & (1 << TABLE_BLOCK)) {
2153 status = table_block_parse(&table_spec,
2163 if (block_mask & (1 << TABLE_BLOCK))
2167 status = rte_swx_pipeline_table_config(p,
2170 table_spec.recommended_table_type_name,
2175 *err_line = n_lines;
2177 *err_msg = "Table configuration error.";
2181 table_spec_free(&table_spec);
2186 /* selector block. */
2187 if (block_mask & (1 << SELECTOR_BLOCK)) {
2188 status = selector_block_parse(&selector_spec,
2198 if (block_mask & (1 << SELECTOR_BLOCK))
2202 status = rte_swx_pipeline_selector_config(p,
2204 &selector_spec.params);
2207 *err_line = n_lines;
2209 *err_msg = "Selector configuration error.";
2213 selector_spec_free(&selector_spec);
2218 /* learner block. */
2219 if (block_mask & (1 << LEARNER_BLOCK)) {
2220 status = learner_block_parse(&learner_spec,
2230 if (block_mask & (1 << LEARNER_BLOCK))
2234 status = rte_swx_pipeline_learner_config(p,
2236 &learner_spec.params,
2238 learner_spec.timeout);
2241 *err_line = n_lines;
2243 *err_msg = "Learner table configuration error.";
2247 learner_spec_free(&learner_spec);
2253 if (block_mask & (1 << APPLY_BLOCK)) {
2254 status = apply_block_parse(&apply_spec,
2264 if (block_mask & (1 << APPLY_BLOCK))
2268 status = rte_swx_pipeline_instructions_config(p,
2269 apply_spec.instructions,
2270 apply_spec.n_instructions);
2273 *err_line = n_lines;
2275 *err_msg = "Pipeline instructions err.";
2279 apply_spec_free(&apply_spec);
2285 if (!strcmp(tokens[0], "extobj")) {
2286 status = extobj_statement_parse(&extobj_spec,
2295 status = rte_swx_pipeline_extern_object_config(p,
2297 extobj_spec.extern_type_name,
2298 extobj_spec.pragma);
2301 *err_line = n_lines;
2303 *err_msg = "Extern object config err.";
2307 extobj_spec_free(&extobj_spec);
2313 if (!strcmp(tokens[0], "struct")) {
2314 status = struct_statement_parse(&struct_spec,
2328 if (!strcmp(tokens[0], "header")) {
2329 status = header_statement_parse(&header_spec,
2338 status = rte_swx_pipeline_packet_header_register(p,
2340 header_spec.struct_type_name);
2343 *err_line = n_lines;
2345 *err_msg = "Header registration error.";
2349 header_spec_free(&header_spec);
2355 if (!strcmp(tokens[0], "metadata")) {
2356 status = metadata_statement_parse(&metadata_spec,
2365 status = rte_swx_pipeline_packet_metadata_register(p,
2366 metadata_spec.struct_type_name);
2369 *err_line = n_lines;
2371 *err_msg = "Meta-data reg err.";
2375 metadata_spec_free(&metadata_spec);
2381 if (!strcmp(tokens[0], "action")) {
2382 status = action_statement_parse(&action_spec,
2396 if (!strcmp(tokens[0], "table")) {
2397 status = table_statement_parse(&table_spec,
2411 if (!strcmp(tokens[0], "selector")) {
2412 status = selector_statement_parse(&selector_spec,
2426 if (!strcmp(tokens[0], "learner")) {
2427 status = learner_statement_parse(&learner_spec,
2441 if (!strcmp(tokens[0], "regarray")) {
2442 status = regarray_statement_parse(®array_spec,
2451 status = rte_swx_pipeline_regarray_config(p,
2454 regarray_spec.init_val);
2457 *err_line = n_lines;
2459 *err_msg = "Register array configuration error.";
2463 regarray_spec_free(®array_spec);
2469 if (!strcmp(tokens[0], "metarray")) {
2470 status = metarray_statement_parse(&metarray_spec,
2479 status = rte_swx_pipeline_metarray_config(p,
2481 metarray_spec.size);
2484 *err_line = n_lines;
2486 *err_msg = "Meter array configuration error.";
2490 metarray_spec_free(&metarray_spec);
2496 if (!strcmp(tokens[0], "apply")) {
2497 status = apply_statement_parse(&block_mask,
2509 /* Anything else. */
2511 *err_line = n_lines;
2513 *err_msg = "Unknown statement.";
2518 /* Handle unfinished block. */
2521 *err_line = n_lines;
2523 *err_msg = "Missing }.";
2528 /* Pipeline build. */
2529 status = rte_swx_pipeline_build(p);
2532 *err_line = n_lines;
2534 *err_msg = "Pipeline build error.";
2541 extobj_spec_free(&extobj_spec);
2542 struct_spec_free(&struct_spec);
2543 header_spec_free(&header_spec);
2544 metadata_spec_free(&metadata_spec);
2545 action_spec_free(&action_spec);
2546 table_spec_free(&table_spec);
2547 selector_spec_free(&selector_spec);
2548 learner_spec_free(&learner_spec);
2549 regarray_spec_free(®array_spec);
2550 metarray_spec_free(&metarray_spec);
2551 apply_spec_free(&apply_spec);