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.";
1296 * ACTION_NAME args METADATA_FIELD_NAME
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 for (i = 0; i < s->params.n_actions; i++) {
1344 uintptr_t name = (uintptr_t)s->params.action_field_names[i];
1349 free(s->params.action_field_names);
1350 s->params.action_field_names = NULL;
1352 s->params.n_actions = 0;
1354 default_action_name = (uintptr_t)s->params.default_action_name;
1355 free((void *)default_action_name);
1356 s->params.default_action_name = NULL;
1358 free(s->params.default_action_data);
1359 s->params.default_action_data = NULL;
1361 s->params.default_action_is_const = 0;
1369 learner_key_statement_parse(uint32_t *block_mask,
1374 const char **err_msg)
1377 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1379 *err_line = n_lines;
1381 *err_msg = "Invalid key statement.";
1386 *block_mask |= 1 << LEARNER_KEY_BLOCK;
1392 learner_key_block_parse(struct learner_spec *s,
1393 uint32_t *block_mask,
1398 const char **err_msg)
1400 const char **new_field_names = NULL;
1401 char *field_name = NULL;
1403 /* Handle end of block. */
1404 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1405 *block_mask &= ~(1 << LEARNER_KEY_BLOCK);
1409 /* Check input arguments. */
1410 if (n_tokens != 1) {
1412 *err_line = n_lines;
1414 *err_msg = "Invalid match field statement.";
1418 field_name = strdup(tokens[0]);
1419 new_field_names = realloc(s->params.field_names, (s->params.n_fields + 1) * sizeof(char *));
1420 if (!field_name || !new_field_names) {
1422 free(new_field_names);
1425 *err_line = n_lines;
1427 *err_msg = "Memory allocation failed.";
1431 s->params.field_names = new_field_names;
1432 s->params.field_names[s->params.n_fields] = field_name;
1433 s->params.n_fields++;
1439 learner_actions_statement_parse(uint32_t *block_mask,
1444 const char **err_msg)
1447 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1449 *err_line = n_lines;
1451 *err_msg = "Invalid actions statement.";
1456 *block_mask |= 1 << LEARNER_ACTIONS_BLOCK;
1462 learner_actions_block_parse(struct learner_spec *s,
1463 uint32_t *block_mask,
1468 const char **err_msg)
1470 const char **new_action_names = NULL;
1471 const char **new_action_field_names = NULL;
1472 char *action_name = NULL, *action_field_name = NULL;
1475 /* Handle end of block. */
1476 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1477 *block_mask &= ~(1 << LEARNER_ACTIONS_BLOCK);
1481 /* Check input arguments. */
1482 if ((n_tokens != 3) || strcmp(tokens[1], "args")) {
1484 *err_line = n_lines;
1486 *err_msg = "Invalid action name statement.";
1490 if (!strcmp(tokens[2], "none"))
1493 action_name = strdup(tokens[0]);
1496 action_field_name = strdup(tokens[2]);
1498 new_action_names = realloc(s->params.action_names,
1499 (s->params.n_actions + 1) * sizeof(char *));
1501 new_action_field_names = realloc(s->params.action_field_names,
1502 (s->params.n_actions + 1) * sizeof(char *));
1505 (has_args && !action_field_name) ||
1506 !new_action_names ||
1507 !new_action_field_names) {
1509 free(action_field_name);
1510 free(new_action_names);
1511 free(new_action_field_names);
1514 *err_line = n_lines;
1516 *err_msg = "Memory allocation failed.";
1520 s->params.action_names = new_action_names;
1521 s->params.action_names[s->params.n_actions] = action_name;
1522 s->params.action_field_names = new_action_field_names;
1523 s->params.action_field_names[s->params.n_actions] = action_field_name;
1524 s->params.n_actions++;
1530 learner_statement_parse(struct learner_spec *s,
1531 uint32_t *block_mask,
1536 const char **err_msg)
1539 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
1541 *err_line = n_lines;
1543 *err_msg = "Invalid learner statement.";
1548 s->name = strdup(tokens[1]);
1551 *err_line = n_lines;
1553 *err_msg = "Memory allocation failed.";
1558 *block_mask |= 1 << LEARNER_BLOCK;
1564 learner_block_parse(struct learner_spec *s,
1565 uint32_t *block_mask,
1570 const char **err_msg)
1572 if (*block_mask & (1 << LEARNER_KEY_BLOCK))
1573 return learner_key_block_parse(s,
1581 if (*block_mask & (1 << LEARNER_ACTIONS_BLOCK))
1582 return learner_actions_block_parse(s,
1590 /* Handle end of block. */
1591 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1592 *block_mask &= ~(1 << LEARNER_BLOCK);
1596 if (!strcmp(tokens[0], "key"))
1597 return learner_key_statement_parse(block_mask,
1604 if (!strcmp(tokens[0], "actions"))
1605 return learner_actions_statement_parse(block_mask,
1612 if (!strcmp(tokens[0], "default_action")) {
1613 if (((n_tokens != 4) && (n_tokens != 5)) ||
1614 strcmp(tokens[2], "args") ||
1615 strcmp(tokens[3], "none") ||
1616 ((n_tokens == 5) && strcmp(tokens[4], "const"))) {
1618 *err_line = n_lines;
1620 *err_msg = "Invalid default_action statement.";
1624 if (s->params.default_action_name) {
1626 *err_line = n_lines;
1628 *err_msg = "Duplicate default_action stmt.";
1632 s->params.default_action_name = strdup(tokens[1]);
1633 if (!s->params.default_action_name) {
1635 *err_line = n_lines;
1637 *err_msg = "Memory allocation failed.";
1642 s->params.default_action_is_const = 1;
1647 if (!strcmp(tokens[0], "size")) {
1648 char *p = tokens[1];
1650 if (n_tokens != 2) {
1652 *err_line = n_lines;
1654 *err_msg = "Invalid size statement.";
1658 s->size = strtoul(p, &p, 0);
1661 *err_line = n_lines;
1663 *err_msg = "Invalid size argument.";
1670 if (!strcmp(tokens[0], "timeout")) {
1671 char *p = tokens[1];
1673 if (n_tokens != 2) {
1675 *err_line = n_lines;
1677 *err_msg = "Invalid timeout statement.";
1681 s->timeout = strtoul(p, &p, 0);
1684 *err_line = n_lines;
1686 *err_msg = "Invalid timeout argument.";
1693 /* Anything else. */
1695 *err_line = n_lines;
1697 *err_msg = "Invalid statement.";
1704 * regarray NAME size SIZE initval INITVAL
1706 struct regarray_spec {
1713 regarray_spec_free(struct regarray_spec *s)
1723 regarray_statement_parse(struct regarray_spec *s,
1728 const char **err_msg)
1733 if ((n_tokens != 6) ||
1734 strcmp(tokens[2], "size") ||
1735 strcmp(tokens[4], "initval")) {
1737 *err_line = n_lines;
1739 *err_msg = "Invalid regarray statement.";
1744 s->name = strdup(tokens[1]);
1747 *err_line = n_lines;
1749 *err_msg = "Memory allocation failed.";
1754 s->size = strtoul(p, &p, 0);
1755 if (p[0] || !s->size) {
1757 *err_line = n_lines;
1759 *err_msg = "Invalid size argument.";
1764 s->init_val = strtoull(p, &p, 0);
1767 *err_line = n_lines;
1769 *err_msg = "Invalid initval argument.";
1779 * metarray NAME size SIZE
1781 struct metarray_spec {
1787 metarray_spec_free(struct metarray_spec *s)
1797 metarray_statement_parse(struct metarray_spec *s,
1802 const char **err_msg)
1807 if ((n_tokens != 4) || strcmp(tokens[2], "size")) {
1809 *err_line = n_lines;
1811 *err_msg = "Invalid metarray statement.";
1816 s->name = strdup(tokens[1]);
1819 *err_line = n_lines;
1821 *err_msg = "Memory allocation failed.";
1826 s->size = strtoul(p, &p, 0);
1827 if (p[0] || !s->size) {
1829 *err_line = n_lines;
1831 *err_msg = "Invalid size argument.";
1847 const char **instructions;
1848 uint32_t n_instructions;
1852 apply_spec_free(struct apply_spec *s)
1859 for (i = 0; i < s->n_instructions; i++) {
1860 uintptr_t instr = (uintptr_t)s->instructions[i];
1862 free((void *)instr);
1865 free(s->instructions);
1866 s->instructions = NULL;
1868 s->n_instructions = 0;
1872 apply_statement_parse(uint32_t *block_mask,
1877 const char **err_msg)
1880 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1882 *err_line = n_lines;
1884 *err_msg = "Invalid apply statement.";
1889 *block_mask |= 1 << APPLY_BLOCK;
1895 apply_block_parse(struct apply_spec *s,
1896 uint32_t *block_mask,
1901 const char **err_msg)
1903 char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr;
1904 const char **new_instructions;
1907 /* Handle end of block. */
1908 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1909 *block_mask &= ~(1 << APPLY_BLOCK);
1915 for (i = 0; i < n_tokens; i++) {
1917 strcat(buffer, " ");
1918 strcat(buffer, tokens[i]);
1921 instr = strdup(buffer);
1924 *err_line = n_lines;
1926 *err_msg = "Memory allocation failed.";
1930 new_instructions = realloc(s->instructions,
1931 (s->n_instructions + 1) * sizeof(char *));
1932 if (!new_instructions) {
1936 *err_line = n_lines;
1938 *err_msg = "Memory allocation failed.";
1942 s->instructions = new_instructions;
1943 s->instructions[s->n_instructions] = instr;
1944 s->n_instructions++;
1953 rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
1956 const char **err_msg)
1958 struct extobj_spec extobj_spec = {0};
1959 struct struct_spec struct_spec = {0};
1960 struct header_spec header_spec = {0};
1961 struct metadata_spec metadata_spec = {0};
1962 struct action_spec action_spec = {0};
1963 struct table_spec table_spec = {0};
1964 struct selector_spec selector_spec = {0};
1965 struct learner_spec learner_spec = {0};
1966 struct regarray_spec regarray_spec = {0};
1967 struct metarray_spec metarray_spec = {0};
1968 struct apply_spec apply_spec = {0};
1970 uint32_t block_mask = 0;
1973 /* Check the input arguments. */
1978 *err_msg = "Null pipeline arument.";
1987 *err_msg = "Null specification file argument.";
1992 for (n_lines = 1; ; n_lines++) {
1993 char line[MAX_LINE_LENGTH];
1994 char *tokens[MAX_TOKENS], *ptr = line;
1995 uint32_t n_tokens = 0;
1997 /* Read next line. */
1998 if (!fgets(line, sizeof(line), spec))
2001 /* Parse the line into tokens. */
2006 token = strtok_r(ptr, " \f\n\r\t\v", &ptr);
2010 /* Handle comments. */
2011 if ((token[0] == '#') ||
2012 (token[0] == ';') ||
2013 ((token[0] == '/') && (token[1] == '/'))) {
2017 /* Handle excessively long lines. */
2018 if (n_tokens >= MAX_TOKENS) {
2020 *err_line = n_lines;
2022 *err_msg = "Too many tokens.";
2027 /* Handle excessively long tokens. */
2028 if (strnlen(token, RTE_SWX_NAME_SIZE) >=
2029 RTE_SWX_NAME_SIZE) {
2031 *err_line = n_lines;
2033 *err_msg = "Token too big.";
2039 tokens[n_tokens] = token;
2043 /* Handle empty lines. */
2048 if (block_mask & (1 << STRUCT_BLOCK)) {
2049 status = struct_block_parse(&struct_spec,
2059 if (block_mask & (1 << STRUCT_BLOCK))
2063 status = rte_swx_pipeline_struct_type_register(p,
2066 struct_spec.n_fields,
2067 struct_spec.varbit);
2070 *err_line = n_lines;
2072 *err_msg = "Struct registration error.";
2076 struct_spec_free(&struct_spec);
2082 if (block_mask & (1 << ACTION_BLOCK)) {
2083 status = action_block_parse(&action_spec,
2093 if (block_mask & (1 << ACTION_BLOCK))
2097 status = rte_swx_pipeline_action_config(p,
2099 action_spec.args_struct_type_name,
2100 action_spec.instructions,
2101 action_spec.n_instructions);
2104 *err_line = n_lines;
2106 *err_msg = "Action config error.";
2110 action_spec_free(&action_spec);
2116 if (block_mask & (1 << TABLE_BLOCK)) {
2117 status = table_block_parse(&table_spec,
2127 if (block_mask & (1 << TABLE_BLOCK))
2131 status = rte_swx_pipeline_table_config(p,
2134 table_spec.recommended_table_type_name,
2139 *err_line = n_lines;
2141 *err_msg = "Table configuration error.";
2145 table_spec_free(&table_spec);
2150 /* selector block. */
2151 if (block_mask & (1 << SELECTOR_BLOCK)) {
2152 status = selector_block_parse(&selector_spec,
2162 if (block_mask & (1 << SELECTOR_BLOCK))
2166 status = rte_swx_pipeline_selector_config(p,
2168 &selector_spec.params);
2171 *err_line = n_lines;
2173 *err_msg = "Selector configuration error.";
2177 selector_spec_free(&selector_spec);
2182 /* learner block. */
2183 if (block_mask & (1 << LEARNER_BLOCK)) {
2184 status = learner_block_parse(&learner_spec,
2194 if (block_mask & (1 << LEARNER_BLOCK))
2198 status = rte_swx_pipeline_learner_config(p,
2200 &learner_spec.params,
2202 learner_spec.timeout);
2205 *err_line = n_lines;
2207 *err_msg = "Learner table configuration error.";
2211 learner_spec_free(&learner_spec);
2217 if (block_mask & (1 << APPLY_BLOCK)) {
2218 status = apply_block_parse(&apply_spec,
2228 if (block_mask & (1 << APPLY_BLOCK))
2232 status = rte_swx_pipeline_instructions_config(p,
2233 apply_spec.instructions,
2234 apply_spec.n_instructions);
2237 *err_line = n_lines;
2239 *err_msg = "Pipeline instructions err.";
2243 apply_spec_free(&apply_spec);
2249 if (!strcmp(tokens[0], "extobj")) {
2250 status = extobj_statement_parse(&extobj_spec,
2259 status = rte_swx_pipeline_extern_object_config(p,
2261 extobj_spec.extern_type_name,
2262 extobj_spec.pragma);
2265 *err_line = n_lines;
2267 *err_msg = "Extern object config err.";
2271 extobj_spec_free(&extobj_spec);
2277 if (!strcmp(tokens[0], "struct")) {
2278 status = struct_statement_parse(&struct_spec,
2292 if (!strcmp(tokens[0], "header")) {
2293 status = header_statement_parse(&header_spec,
2302 status = rte_swx_pipeline_packet_header_register(p,
2304 header_spec.struct_type_name);
2307 *err_line = n_lines;
2309 *err_msg = "Header registration error.";
2313 header_spec_free(&header_spec);
2319 if (!strcmp(tokens[0], "metadata")) {
2320 status = metadata_statement_parse(&metadata_spec,
2329 status = rte_swx_pipeline_packet_metadata_register(p,
2330 metadata_spec.struct_type_name);
2333 *err_line = n_lines;
2335 *err_msg = "Meta-data reg err.";
2339 metadata_spec_free(&metadata_spec);
2345 if (!strcmp(tokens[0], "action")) {
2346 status = action_statement_parse(&action_spec,
2360 if (!strcmp(tokens[0], "table")) {
2361 status = table_statement_parse(&table_spec,
2375 if (!strcmp(tokens[0], "selector")) {
2376 status = selector_statement_parse(&selector_spec,
2390 if (!strcmp(tokens[0], "learner")) {
2391 status = learner_statement_parse(&learner_spec,
2405 if (!strcmp(tokens[0], "regarray")) {
2406 status = regarray_statement_parse(®array_spec,
2415 status = rte_swx_pipeline_regarray_config(p,
2418 regarray_spec.init_val);
2421 *err_line = n_lines;
2423 *err_msg = "Register array configuration error.";
2427 regarray_spec_free(®array_spec);
2433 if (!strcmp(tokens[0], "metarray")) {
2434 status = metarray_statement_parse(&metarray_spec,
2443 status = rte_swx_pipeline_metarray_config(p,
2445 metarray_spec.size);
2448 *err_line = n_lines;
2450 *err_msg = "Meter array configuration error.";
2454 metarray_spec_free(&metarray_spec);
2460 if (!strcmp(tokens[0], "apply")) {
2461 status = apply_statement_parse(&block_mask,
2473 /* Anything else. */
2475 *err_line = n_lines;
2477 *err_msg = "Unknown statement.";
2482 /* Handle unfinished block. */
2485 *err_line = n_lines;
2487 *err_msg = "Missing }.";
2492 /* Pipeline build. */
2493 status = rte_swx_pipeline_build(p);
2496 *err_line = n_lines;
2498 *err_msg = "Pipeline build error.";
2505 extobj_spec_free(&extobj_spec);
2506 struct_spec_free(&struct_spec);
2507 header_spec_free(&header_spec);
2508 metadata_spec_free(&metadata_spec);
2509 action_spec_free(&action_spec);
2510 table_spec_free(&table_spec);
2511 selector_spec_free(&selector_spec);
2512 learner_spec_free(&learner_spec);
2513 regarray_spec_free(®array_spec);
2514 metarray_spec_free(&metarray_spec);
2515 apply_spec_free(&apply_spec);