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
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 s->params.default_action_is_const = 0;
602 free(s->recommended_table_type_name);
603 s->recommended_table_type_name = NULL;
612 table_key_statement_parse(uint32_t *block_mask,
617 const char **err_msg)
620 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
624 *err_msg = "Invalid key statement.";
629 *block_mask |= 1 << TABLE_KEY_BLOCK;
635 table_key_block_parse(struct table_spec *s,
636 uint32_t *block_mask,
641 const char **err_msg)
643 struct rte_swx_match_field_params *new_fields;
644 enum rte_swx_table_match_type match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
647 /* Handle end of block. */
648 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
649 *block_mask &= ~(1 << TABLE_KEY_BLOCK);
653 /* Check input arguments. */
654 if ((n_tokens != 2) ||
655 (strcmp(tokens[1], "exact") &&
656 strcmp(tokens[1], "wildcard") &&
657 strcmp(tokens[1], "lpm"))) {
661 *err_msg = "Invalid match field statement.";
665 if (!strcmp(tokens[1], "wildcard"))
666 match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
667 if (!strcmp(tokens[1], "lpm"))
668 match_type = RTE_SWX_TABLE_MATCH_LPM;
669 if (!strcmp(tokens[1], "exact"))
670 match_type = RTE_SWX_TABLE_MATCH_EXACT;
672 name = strdup(tokens[0]);
677 *err_msg = "Memory allocation failed.";
681 new_fields = realloc(s->params.fields,
682 (s->params.n_fields + 1) * sizeof(struct rte_swx_match_field_params));
689 *err_msg = "Memory allocation failed.";
693 s->params.fields = new_fields;
694 s->params.fields[s->params.n_fields].name = name;
695 s->params.fields[s->params.n_fields].match_type = match_type;
696 s->params.n_fields++;
702 table_actions_statement_parse(uint32_t *block_mask,
707 const char **err_msg)
710 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
714 *err_msg = "Invalid actions statement.";
719 *block_mask |= 1 << TABLE_ACTIONS_BLOCK;
725 table_actions_block_parse(struct table_spec *s,
726 uint32_t *block_mask,
731 const char **err_msg)
733 const char **new_action_names;
736 /* Handle end of block. */
737 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
738 *block_mask &= ~(1 << TABLE_ACTIONS_BLOCK);
742 /* Check input arguments. */
747 *err_msg = "Invalid action name statement.";
751 name = strdup(tokens[0]);
756 *err_msg = "Memory allocation failed.";
760 new_action_names = realloc(s->params.action_names,
761 (s->params.n_actions + 1) * sizeof(char *));
762 if (!new_action_names) {
768 *err_msg = "Memory allocation failed.";
772 s->params.action_names = new_action_names;
773 s->params.action_names[s->params.n_actions] = name;
774 s->params.n_actions++;
780 table_statement_parse(struct table_spec *s,
781 uint32_t *block_mask,
786 const char **err_msg)
789 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
793 *err_msg = "Invalid table statement.";
798 s->name = strdup(tokens[1]);
803 *err_msg = "Memory allocation failed.";
808 *block_mask |= 1 << TABLE_BLOCK;
814 table_block_parse(struct table_spec *s,
815 uint32_t *block_mask,
820 const char **err_msg)
822 if (*block_mask & (1 << TABLE_KEY_BLOCK))
823 return table_key_block_parse(s,
831 if (*block_mask & (1 << TABLE_ACTIONS_BLOCK))
832 return table_actions_block_parse(s,
840 /* Handle end of block. */
841 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
842 *block_mask &= ~(1 << TABLE_BLOCK);
846 if (!strcmp(tokens[0], "key"))
847 return table_key_statement_parse(block_mask,
854 if (!strcmp(tokens[0], "actions"))
855 return table_actions_statement_parse(block_mask,
862 if (!strcmp(tokens[0], "default_action")) {
863 if (((n_tokens != 4) && (n_tokens != 5)) ||
864 strcmp(tokens[2], "args") ||
865 strcmp(tokens[3], "none") ||
866 ((n_tokens == 5) && strcmp(tokens[4], "const"))) {
870 *err_msg = "Invalid default_action statement.";
874 if (s->params.default_action_name) {
878 *err_msg = "Duplicate default_action stmt.";
882 s->params.default_action_name = strdup(tokens[1]);
883 if (!s->params.default_action_name) {
887 *err_msg = "Memory allocation failed.";
892 s->params.default_action_is_const = 1;
897 if (!strcmp(tokens[0], "instanceof")) {
902 *err_msg = "Invalid instanceof statement.";
906 if (s->recommended_table_type_name) {
910 *err_msg = "Duplicate instanceof statement.";
914 s->recommended_table_type_name = strdup(tokens[1]);
915 if (!s->recommended_table_type_name) {
919 *err_msg = "Memory allocation failed.";
926 if (!strcmp(tokens[0], "pragma")) {
931 *err_msg = "Invalid pragma statement.";
939 *err_msg = "Duplicate pragma statement.";
943 s->args = strdup(tokens[1]);
948 *err_msg = "Memory allocation failed.";
955 if (!strcmp(tokens[0], "size")) {
962 *err_msg = "Invalid pragma statement.";
966 s->size = strtoul(p, &p, 0);
971 *err_msg = "Invalid size argument.";
982 *err_msg = "Invalid statement.";
989 * selector SELECTOR_NAME {
990 * group_id FIELD_NAME
995 * member_id FIELD_NAME
997 * n_members_per_group N_MEMBERS_PER_GROUP
1000 struct selector_spec {
1002 struct rte_swx_pipeline_selector_params params;
1006 selector_spec_free(struct selector_spec *s)
1008 uintptr_t field_name;
1018 /* params->group_id_field_name. */
1019 field_name = (uintptr_t)s->params.group_id_field_name;
1020 free((void *)field_name);
1021 s->params.group_id_field_name = NULL;
1023 /* params->selector_field_names. */
1024 for (i = 0; i < s->params.n_selector_fields; i++) {
1025 field_name = (uintptr_t)s->params.selector_field_names[i];
1027 free((void *)field_name);
1030 free(s->params.selector_field_names);
1031 s->params.selector_field_names = NULL;
1033 s->params.n_selector_fields = 0;
1035 /* params->member_id_field_name. */
1036 field_name = (uintptr_t)s->params.member_id_field_name;
1037 free((void *)field_name);
1038 s->params.member_id_field_name = NULL;
1040 /* params->n_groups_max. */
1041 s->params.n_groups_max = 0;
1043 /* params->n_members_per_group_max. */
1044 s->params.n_members_per_group_max = 0;
1048 selector_statement_parse(struct selector_spec *s,
1049 uint32_t *block_mask,
1054 const char **err_msg)
1057 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
1059 *err_line = n_lines;
1061 *err_msg = "Invalid selector statement.";
1066 s->name = strdup(tokens[1]);
1069 *err_line = n_lines;
1071 *err_msg = "Memory allocation failed.";
1076 *block_mask |= 1 << SELECTOR_BLOCK;
1082 selector_selector_statement_parse(uint32_t *block_mask,
1087 const char **err_msg)
1090 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1092 *err_line = n_lines;
1094 *err_msg = "Invalid selector statement.";
1099 *block_mask |= 1 << SELECTOR_SELECTOR_BLOCK;
1105 selector_selector_block_parse(struct selector_spec *s,
1106 uint32_t *block_mask,
1111 const char **err_msg)
1113 const char **new_fields;
1116 /* Handle end of block. */
1117 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1118 *block_mask &= ~(1 << SELECTOR_SELECTOR_BLOCK);
1122 /* Check input arguments. */
1123 if (n_tokens != 1) {
1125 *err_line = n_lines;
1127 *err_msg = "Invalid selector field statement.";
1131 name = strdup(tokens[0]);
1134 *err_line = n_lines;
1136 *err_msg = "Memory allocation failed.";
1140 new_fields = realloc(s->params.selector_field_names,
1141 (s->params.n_selector_fields + 1) * sizeof(char *));
1146 *err_line = n_lines;
1148 *err_msg = "Memory allocation failed.";
1152 s->params.selector_field_names = new_fields;
1153 s->params.selector_field_names[s->params.n_selector_fields] = name;
1154 s->params.n_selector_fields++;
1160 selector_block_parse(struct selector_spec *s,
1161 uint32_t *block_mask,
1166 const char **err_msg)
1168 if (*block_mask & (1 << SELECTOR_SELECTOR_BLOCK))
1169 return selector_selector_block_parse(s,
1177 /* Handle end of block. */
1178 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1179 *block_mask &= ~(1 << SELECTOR_BLOCK);
1183 if (!strcmp(tokens[0], "group_id")) {
1184 if (n_tokens != 2) {
1186 *err_line = n_lines;
1188 *err_msg = "Invalid group_id statement.";
1192 s->params.group_id_field_name = strdup(tokens[1]);
1193 if (!s->params.group_id_field_name) {
1195 *err_line = n_lines;
1197 *err_msg = "Memory allocation failed.";
1204 if (!strcmp(tokens[0], "selector"))
1205 return selector_selector_statement_parse(block_mask,
1212 if (!strcmp(tokens[0], "member_id")) {
1213 if (n_tokens != 2) {
1215 *err_line = n_lines;
1217 *err_msg = "Invalid member_id statement.";
1221 s->params.member_id_field_name = strdup(tokens[1]);
1222 if (!s->params.member_id_field_name) {
1224 *err_line = n_lines;
1226 *err_msg = "Memory allocation failed.";
1233 if (!strcmp(tokens[0], "n_groups_max")) {
1234 char *p = tokens[1];
1236 if (n_tokens != 2) {
1238 *err_line = n_lines;
1240 *err_msg = "Invalid n_groups statement.";
1244 s->params.n_groups_max = strtoul(p, &p, 0);
1247 *err_line = n_lines;
1249 *err_msg = "Invalid n_groups argument.";
1256 if (!strcmp(tokens[0], "n_members_per_group_max")) {
1257 char *p = tokens[1];
1259 if (n_tokens != 2) {
1261 *err_line = n_lines;
1263 *err_msg = "Invalid n_members_per_group statement.";
1267 s->params.n_members_per_group_max = strtoul(p, &p, 0);
1270 *err_line = n_lines;
1272 *err_msg = "Invalid n_members_per_group argument.";
1279 /* Anything else. */
1281 *err_line = n_lines;
1283 *err_msg = "Invalid statement.";
1299 * default_action ACTION_NAME args none | ARGS_BYTE_ARRAY [ const ]
1301 * timeout TIMEOUT_IN_SECONDS
1304 struct learner_spec {
1306 struct rte_swx_pipeline_learner_params params;
1312 learner_spec_free(struct learner_spec *s)
1314 uintptr_t default_action_name;
1323 for (i = 0; i < s->params.n_fields; i++) {
1324 uintptr_t name = (uintptr_t)s->params.field_names[i];
1329 free(s->params.field_names);
1330 s->params.field_names = NULL;
1332 s->params.n_fields = 0;
1334 for (i = 0; i < s->params.n_actions; i++) {
1335 uintptr_t name = (uintptr_t)s->params.action_names[i];
1340 free(s->params.action_names);
1341 s->params.action_names = NULL;
1343 s->params.n_actions = 0;
1345 default_action_name = (uintptr_t)s->params.default_action_name;
1346 free((void *)default_action_name);
1347 s->params.default_action_name = NULL;
1349 free(s->params.default_action_data);
1350 s->params.default_action_data = NULL;
1352 s->params.default_action_is_const = 0;
1360 learner_key_statement_parse(uint32_t *block_mask,
1365 const char **err_msg)
1368 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1370 *err_line = n_lines;
1372 *err_msg = "Invalid key statement.";
1377 *block_mask |= 1 << LEARNER_KEY_BLOCK;
1383 learner_key_block_parse(struct learner_spec *s,
1384 uint32_t *block_mask,
1389 const char **err_msg)
1391 const char **new_field_names = NULL;
1392 char *field_name = NULL;
1394 /* Handle end of block. */
1395 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1396 *block_mask &= ~(1 << LEARNER_KEY_BLOCK);
1400 /* Check input arguments. */
1401 if (n_tokens != 1) {
1403 *err_line = n_lines;
1405 *err_msg = "Invalid match field statement.";
1409 field_name = strdup(tokens[0]);
1410 new_field_names = realloc(s->params.field_names, (s->params.n_fields + 1) * sizeof(char *));
1411 if (!field_name || !new_field_names) {
1413 free(new_field_names);
1416 *err_line = n_lines;
1418 *err_msg = "Memory allocation failed.";
1422 s->params.field_names = new_field_names;
1423 s->params.field_names[s->params.n_fields] = field_name;
1424 s->params.n_fields++;
1430 learner_actions_statement_parse(uint32_t *block_mask,
1435 const char **err_msg)
1438 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1440 *err_line = n_lines;
1442 *err_msg = "Invalid actions statement.";
1447 *block_mask |= 1 << LEARNER_ACTIONS_BLOCK;
1453 learner_actions_block_parse(struct learner_spec *s,
1454 uint32_t *block_mask,
1459 const char **err_msg)
1461 const char **new_action_names = NULL;
1462 char *action_name = NULL;
1464 /* Handle end of block. */
1465 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1466 *block_mask &= ~(1 << LEARNER_ACTIONS_BLOCK);
1470 /* Check input arguments. */
1471 if (n_tokens != 1) {
1473 *err_line = n_lines;
1475 *err_msg = "Invalid action name statement.";
1479 action_name = strdup(tokens[0]);
1481 new_action_names = realloc(s->params.action_names,
1482 (s->params.n_actions + 1) * sizeof(char *));
1484 if (!action_name || !new_action_names) {
1486 free(new_action_names);
1489 *err_line = n_lines;
1491 *err_msg = "Memory allocation failed.";
1495 s->params.action_names = new_action_names;
1496 s->params.action_names[s->params.n_actions] = action_name;
1497 s->params.n_actions++;
1503 learner_statement_parse(struct learner_spec *s,
1504 uint32_t *block_mask,
1509 const char **err_msg)
1512 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
1514 *err_line = n_lines;
1516 *err_msg = "Invalid learner statement.";
1521 s->name = strdup(tokens[1]);
1524 *err_line = n_lines;
1526 *err_msg = "Memory allocation failed.";
1531 *block_mask |= 1 << LEARNER_BLOCK;
1537 learner_block_parse(struct learner_spec *s,
1538 uint32_t *block_mask,
1543 const char **err_msg)
1545 if (*block_mask & (1 << LEARNER_KEY_BLOCK))
1546 return learner_key_block_parse(s,
1554 if (*block_mask & (1 << LEARNER_ACTIONS_BLOCK))
1555 return learner_actions_block_parse(s,
1563 /* Handle end of block. */
1564 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1565 *block_mask &= ~(1 << LEARNER_BLOCK);
1569 if (!strcmp(tokens[0], "key"))
1570 return learner_key_statement_parse(block_mask,
1577 if (!strcmp(tokens[0], "actions"))
1578 return learner_actions_statement_parse(block_mask,
1585 if (!strcmp(tokens[0], "default_action")) {
1586 if (((n_tokens != 4) && (n_tokens != 5)) ||
1587 strcmp(tokens[2], "args") ||
1588 strcmp(tokens[3], "none") ||
1589 ((n_tokens == 5) && strcmp(tokens[4], "const"))) {
1591 *err_line = n_lines;
1593 *err_msg = "Invalid default_action statement.";
1597 if (s->params.default_action_name) {
1599 *err_line = n_lines;
1601 *err_msg = "Duplicate default_action stmt.";
1605 s->params.default_action_name = strdup(tokens[1]);
1606 if (!s->params.default_action_name) {
1608 *err_line = n_lines;
1610 *err_msg = "Memory allocation failed.";
1615 s->params.default_action_is_const = 1;
1620 if (!strcmp(tokens[0], "size")) {
1621 char *p = tokens[1];
1623 if (n_tokens != 2) {
1625 *err_line = n_lines;
1627 *err_msg = "Invalid size statement.";
1631 s->size = strtoul(p, &p, 0);
1634 *err_line = n_lines;
1636 *err_msg = "Invalid size argument.";
1643 if (!strcmp(tokens[0], "timeout")) {
1644 char *p = tokens[1];
1646 if (n_tokens != 2) {
1648 *err_line = n_lines;
1650 *err_msg = "Invalid timeout statement.";
1654 s->timeout = strtoul(p, &p, 0);
1657 *err_line = n_lines;
1659 *err_msg = "Invalid timeout argument.";
1666 /* Anything else. */
1668 *err_line = n_lines;
1670 *err_msg = "Invalid statement.";
1677 * regarray NAME size SIZE initval INITVAL
1679 struct regarray_spec {
1686 regarray_spec_free(struct regarray_spec *s)
1696 regarray_statement_parse(struct regarray_spec *s,
1701 const char **err_msg)
1706 if ((n_tokens != 6) ||
1707 strcmp(tokens[2], "size") ||
1708 strcmp(tokens[4], "initval")) {
1710 *err_line = n_lines;
1712 *err_msg = "Invalid regarray statement.";
1717 s->name = strdup(tokens[1]);
1720 *err_line = n_lines;
1722 *err_msg = "Memory allocation failed.";
1727 s->size = strtoul(p, &p, 0);
1728 if (p[0] || !s->size) {
1730 *err_line = n_lines;
1732 *err_msg = "Invalid size argument.";
1737 s->init_val = strtoull(p, &p, 0);
1740 *err_line = n_lines;
1742 *err_msg = "Invalid initval argument.";
1752 * metarray NAME size SIZE
1754 struct metarray_spec {
1760 metarray_spec_free(struct metarray_spec *s)
1770 metarray_statement_parse(struct metarray_spec *s,
1775 const char **err_msg)
1780 if ((n_tokens != 4) || strcmp(tokens[2], "size")) {
1782 *err_line = n_lines;
1784 *err_msg = "Invalid metarray statement.";
1789 s->name = strdup(tokens[1]);
1792 *err_line = n_lines;
1794 *err_msg = "Memory allocation failed.";
1799 s->size = strtoul(p, &p, 0);
1800 if (p[0] || !s->size) {
1802 *err_line = n_lines;
1804 *err_msg = "Invalid size argument.";
1820 const char **instructions;
1821 uint32_t n_instructions;
1825 apply_spec_free(struct apply_spec *s)
1832 for (i = 0; i < s->n_instructions; i++) {
1833 uintptr_t instr = (uintptr_t)s->instructions[i];
1835 free((void *)instr);
1838 free(s->instructions);
1839 s->instructions = NULL;
1841 s->n_instructions = 0;
1845 apply_statement_parse(uint32_t *block_mask,
1850 const char **err_msg)
1853 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1855 *err_line = n_lines;
1857 *err_msg = "Invalid apply statement.";
1862 *block_mask |= 1 << APPLY_BLOCK;
1868 apply_block_parse(struct apply_spec *s,
1869 uint32_t *block_mask,
1874 const char **err_msg)
1876 char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr;
1877 const char **new_instructions;
1880 /* Handle end of block. */
1881 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1882 *block_mask &= ~(1 << APPLY_BLOCK);
1888 for (i = 0; i < n_tokens; i++) {
1890 strcat(buffer, " ");
1891 strcat(buffer, tokens[i]);
1894 instr = strdup(buffer);
1897 *err_line = n_lines;
1899 *err_msg = "Memory allocation failed.";
1903 new_instructions = realloc(s->instructions,
1904 (s->n_instructions + 1) * sizeof(char *));
1905 if (!new_instructions) {
1909 *err_line = n_lines;
1911 *err_msg = "Memory allocation failed.";
1915 s->instructions = new_instructions;
1916 s->instructions[s->n_instructions] = instr;
1917 s->n_instructions++;
1926 rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
1929 const char **err_msg)
1931 struct extobj_spec extobj_spec = {0};
1932 struct struct_spec struct_spec = {0};
1933 struct header_spec header_spec = {0};
1934 struct metadata_spec metadata_spec = {0};
1935 struct action_spec action_spec = {0};
1936 struct table_spec table_spec = {0};
1937 struct selector_spec selector_spec = {0};
1938 struct learner_spec learner_spec = {0};
1939 struct regarray_spec regarray_spec = {0};
1940 struct metarray_spec metarray_spec = {0};
1941 struct apply_spec apply_spec = {0};
1943 uint32_t block_mask = 0;
1946 /* Check the input arguments. */
1951 *err_msg = "Null pipeline arument.";
1960 *err_msg = "Null specification file argument.";
1965 for (n_lines = 1; ; n_lines++) {
1966 char line[MAX_LINE_LENGTH];
1967 char *tokens[MAX_TOKENS], *ptr = line;
1968 uint32_t n_tokens = 0;
1970 /* Read next line. */
1971 if (!fgets(line, sizeof(line), spec))
1974 /* Parse the line into tokens. */
1979 token = strtok_r(ptr, " \f\n\r\t\v", &ptr);
1983 /* Handle comments. */
1984 if ((token[0] == '#') ||
1985 (token[0] == ';') ||
1986 ((token[0] == '/') && (token[1] == '/'))) {
1990 /* Handle excessively long lines. */
1991 if (n_tokens >= MAX_TOKENS) {
1993 *err_line = n_lines;
1995 *err_msg = "Too many tokens.";
2000 /* Handle excessively long tokens. */
2001 if (strnlen(token, RTE_SWX_NAME_SIZE) >=
2002 RTE_SWX_NAME_SIZE) {
2004 *err_line = n_lines;
2006 *err_msg = "Token too big.";
2012 tokens[n_tokens] = token;
2016 /* Handle empty lines. */
2021 if (block_mask & (1 << STRUCT_BLOCK)) {
2022 status = struct_block_parse(&struct_spec,
2032 if (block_mask & (1 << STRUCT_BLOCK))
2036 status = rte_swx_pipeline_struct_type_register(p,
2039 struct_spec.n_fields,
2040 struct_spec.varbit);
2043 *err_line = n_lines;
2045 *err_msg = "Struct registration error.";
2049 struct_spec_free(&struct_spec);
2055 if (block_mask & (1 << ACTION_BLOCK)) {
2056 status = action_block_parse(&action_spec,
2066 if (block_mask & (1 << ACTION_BLOCK))
2070 status = rte_swx_pipeline_action_config(p,
2072 action_spec.args_struct_type_name,
2073 action_spec.instructions,
2074 action_spec.n_instructions);
2077 *err_line = n_lines;
2079 *err_msg = "Action config error.";
2083 action_spec_free(&action_spec);
2089 if (block_mask & (1 << TABLE_BLOCK)) {
2090 status = table_block_parse(&table_spec,
2100 if (block_mask & (1 << TABLE_BLOCK))
2104 status = rte_swx_pipeline_table_config(p,
2107 table_spec.recommended_table_type_name,
2112 *err_line = n_lines;
2114 *err_msg = "Table configuration error.";
2118 table_spec_free(&table_spec);
2123 /* selector block. */
2124 if (block_mask & (1 << SELECTOR_BLOCK)) {
2125 status = selector_block_parse(&selector_spec,
2135 if (block_mask & (1 << SELECTOR_BLOCK))
2139 status = rte_swx_pipeline_selector_config(p,
2141 &selector_spec.params);
2144 *err_line = n_lines;
2146 *err_msg = "Selector configuration error.";
2150 selector_spec_free(&selector_spec);
2155 /* learner block. */
2156 if (block_mask & (1 << LEARNER_BLOCK)) {
2157 status = learner_block_parse(&learner_spec,
2167 if (block_mask & (1 << LEARNER_BLOCK))
2171 status = rte_swx_pipeline_learner_config(p,
2173 &learner_spec.params,
2175 learner_spec.timeout);
2178 *err_line = n_lines;
2180 *err_msg = "Learner table configuration error.";
2184 learner_spec_free(&learner_spec);
2190 if (block_mask & (1 << APPLY_BLOCK)) {
2191 status = apply_block_parse(&apply_spec,
2201 if (block_mask & (1 << APPLY_BLOCK))
2205 status = rte_swx_pipeline_instructions_config(p,
2206 apply_spec.instructions,
2207 apply_spec.n_instructions);
2210 *err_line = n_lines;
2212 *err_msg = "Pipeline instructions err.";
2216 apply_spec_free(&apply_spec);
2222 if (!strcmp(tokens[0], "extobj")) {
2223 status = extobj_statement_parse(&extobj_spec,
2232 status = rte_swx_pipeline_extern_object_config(p,
2234 extobj_spec.extern_type_name,
2235 extobj_spec.pragma);
2238 *err_line = n_lines;
2240 *err_msg = "Extern object config err.";
2244 extobj_spec_free(&extobj_spec);
2250 if (!strcmp(tokens[0], "struct")) {
2251 status = struct_statement_parse(&struct_spec,
2265 if (!strcmp(tokens[0], "header")) {
2266 status = header_statement_parse(&header_spec,
2275 status = rte_swx_pipeline_packet_header_register(p,
2277 header_spec.struct_type_name);
2280 *err_line = n_lines;
2282 *err_msg = "Header registration error.";
2286 header_spec_free(&header_spec);
2292 if (!strcmp(tokens[0], "metadata")) {
2293 status = metadata_statement_parse(&metadata_spec,
2302 status = rte_swx_pipeline_packet_metadata_register(p,
2303 metadata_spec.struct_type_name);
2306 *err_line = n_lines;
2308 *err_msg = "Meta-data reg err.";
2312 metadata_spec_free(&metadata_spec);
2318 if (!strcmp(tokens[0], "action")) {
2319 status = action_statement_parse(&action_spec,
2333 if (!strcmp(tokens[0], "table")) {
2334 status = table_statement_parse(&table_spec,
2348 if (!strcmp(tokens[0], "selector")) {
2349 status = selector_statement_parse(&selector_spec,
2363 if (!strcmp(tokens[0], "learner")) {
2364 status = learner_statement_parse(&learner_spec,
2378 if (!strcmp(tokens[0], "regarray")) {
2379 status = regarray_statement_parse(®array_spec,
2388 status = rte_swx_pipeline_regarray_config(p,
2391 regarray_spec.init_val);
2394 *err_line = n_lines;
2396 *err_msg = "Register array configuration error.";
2400 regarray_spec_free(®array_spec);
2406 if (!strcmp(tokens[0], "metarray")) {
2407 status = metarray_statement_parse(&metarray_spec,
2416 status = rte_swx_pipeline_metarray_config(p,
2418 metarray_spec.size);
2421 *err_line = n_lines;
2423 *err_msg = "Meter array configuration error.";
2427 metarray_spec_free(&metarray_spec);
2433 if (!strcmp(tokens[0], "apply")) {
2434 status = apply_statement_parse(&block_mask,
2446 /* Anything else. */
2448 *err_line = n_lines;
2450 *err_msg = "Unknown statement.";
2455 /* Handle unfinished block. */
2458 *err_line = n_lines;
2460 *err_msg = "Missing }.";
2465 /* Pipeline build. */
2466 status = rte_swx_pipeline_build(p);
2469 *err_line = n_lines;
2471 *err_msg = "Pipeline build error.";
2478 extobj_spec_free(&extobj_spec);
2479 struct_spec_free(&struct_spec);
2480 header_spec_free(&header_spec);
2481 metadata_spec_free(&metadata_spec);
2482 action_spec_free(&action_spec);
2483 table_spec_free(&table_spec);
2484 selector_spec_free(&selector_spec);
2485 learner_spec_free(&learner_spec);
2486 regarray_spec_free(®array_spec);
2487 metarray_spec_free(&metarray_spec);
2488 apply_spec_free(&apply_spec);