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 256
15 #define MAX_INSTRUCTION_LENGTH 256
17 #define STRUCT_BLOCK 0
18 #define ACTION_BLOCK 1
20 #define TABLE_KEY_BLOCK 3
21 #define TABLE_ACTIONS_BLOCK 4
27 * extobj OBJ_NAME instanceof OBJ_TYPE [ pragma OBJ_CREATE_ARGS ]
31 char *extern_type_name;
36 extobj_spec_free(struct extobj_spec *s)
39 free(s->extern_type_name);
44 extobj_statement_parse(struct extobj_spec *s,
52 if (((n_tokens != 4) && (n_tokens != 6)) ||
53 ((n_tokens == 4) && strcmp(tokens[2], "instanceof")) ||
54 ((n_tokens == 6) && (strcmp(tokens[2], "instanceof") ||
55 strcmp(tokens[4], "pragma")))) {
59 *err_msg = "Invalid extobj statement.";
64 s->name = strdup(tokens[1]);
65 s->extern_type_name = strdup(tokens[3]);
66 s->pragma = (n_tokens == 6) ? strdup(tokens[5]) : NULL;
69 !s->extern_type_name ||
70 ((n_tokens == 6) && !s->pragma)) {
72 free(s->extern_type_name);
78 *err_msg = "Memory allocation failed.";
88 * struct STRUCT_TYPE_NAME {
89 * bit<SIZE> FIELD_NAME
95 struct rte_swx_field_params *fields;
100 struct_spec_free(struct struct_spec *s)
110 for (i = 0; i < s->n_fields; i++) {
111 uintptr_t name = (uintptr_t)s->fields[i].name;
123 struct_statement_parse(struct struct_spec *s,
124 uint32_t *block_mask,
129 const char **err_msg)
132 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
136 *err_msg = "Invalid struct statement.";
141 s->name = strdup(tokens[1]);
146 *err_msg = "Memory allocation failed.";
151 *block_mask |= 1 << STRUCT_BLOCK;
157 struct_block_parse(struct struct_spec *s,
158 uint32_t *block_mask,
163 const char **err_msg)
165 struct rte_swx_field_params *new_fields;
166 char *p = tokens[0], *name;
169 /* Handle end of block. */
170 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
171 *block_mask &= ~(1 << STRUCT_BLOCK);
176 if ((n_tokens != 2) ||
182 (p[strlen(p) - 1] != '>')) {
186 *err_msg = "Invalid struct field statement.";
190 /* Remove the "bit<" and ">". */
191 p[strlen(p) - 1] = 0;
194 n_bits = strtoul(p, &p, 0);
202 *err_msg = "Invalid struct field size.";
207 name = strdup(tokens[1]);
212 *err_msg = "Memory allocation failed.";
216 new_fields = reallocarray(s->fields,
218 sizeof(struct rte_swx_field_params));
225 *err_msg = "Memory allocation failed.";
229 s->fields = new_fields;
230 s->fields[s->n_fields].name = name;
231 s->fields[s->n_fields].n_bits = n_bits;
240 * header HEADER_NAME instanceof STRUCT_TYPE_NAME
244 char *struct_type_name;
248 header_spec_free(struct header_spec *s)
251 free(s->struct_type_name);
255 header_statement_parse(struct header_spec *s,
260 const char **err_msg)
263 if ((n_tokens != 4) || strcmp(tokens[2], "instanceof")) {
267 *err_msg = "Invalid header statement.";
272 s->name = strdup(tokens[1]);
273 s->struct_type_name = strdup(tokens[3]);
275 if (!s->name || !s->struct_type_name) {
277 free(s->struct_type_name);
282 *err_msg = "Memory allocation failed.";
292 * metadata instanceof STRUCT_TYPE_NAME
294 struct metadata_spec {
295 char *struct_type_name;
299 metadata_spec_free(struct metadata_spec *s)
301 free(s->struct_type_name);
305 metadata_statement_parse(struct metadata_spec *s,
310 const char **err_msg)
313 if ((n_tokens != 3) || strcmp(tokens[1], "instanceof")) {
317 *err_msg = "Invalid metadata statement.";
322 s->struct_type_name = strdup(tokens[2]);
323 if (!s->struct_type_name) {
327 *err_msg = "Memory allocation failed.";
337 * action ACTION_NAME args none | instanceof STRUCT_TYPE_NAME {
344 char *args_struct_type_name;
345 const char **instructions;
346 uint32_t n_instructions;
350 action_spec_free(struct action_spec *s)
360 free(s->args_struct_type_name);
361 s->args_struct_type_name = NULL;
363 for (i = 0; i < s->n_instructions; i++) {
364 uintptr_t instr = (uintptr_t)s->instructions[i];
369 free(s->instructions);
370 s->instructions = NULL;
372 s->n_instructions = 0;
376 action_statement_parse(struct action_spec *s,
377 uint32_t *block_mask,
382 const char **err_msg)
385 if (((n_tokens != 5) && (n_tokens != 6)) ||
387 (strcmp(tokens[2], "args") ||
388 strcmp(tokens[3], "none") ||
389 strcmp(tokens[4], "{"))) ||
391 (strcmp(tokens[2], "args") ||
392 strcmp(tokens[3], "instanceof") ||
393 strcmp(tokens[5], "{")))) {
397 *err_msg = "Invalid action statement.";
402 s->name = strdup(tokens[1]);
403 s->args_struct_type_name = (n_tokens == 6) ? strdup(tokens[4]) : NULL;
405 if ((!s->name) || ((n_tokens == 6) && !s->args_struct_type_name)) {
409 *err_msg = "Memory allocation failed.";
414 *block_mask |= 1 << ACTION_BLOCK;
420 action_block_parse(struct action_spec *s,
421 uint32_t *block_mask,
426 const char **err_msg)
428 char buffer[MAX_INSTRUCTION_LENGTH], *instr;
429 const char **new_instructions;
432 /* Handle end of block. */
433 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
434 *block_mask &= ~(1 << ACTION_BLOCK);
440 for (i = 0; i < n_tokens; i++) {
443 strcat(buffer, tokens[i]);
446 instr = strdup(buffer);
451 *err_msg = "Memory allocation failed.";
455 new_instructions = reallocarray(s->instructions,
456 s->n_instructions + 1,
458 if (!new_instructions) {
464 *err_msg = "Memory allocation failed.";
468 s->instructions = new_instructions;
469 s->instructions[s->n_instructions] = instr;
480 * MATCH_FIELD_NAME exact | wildcard | lpm
487 * default_action ACTION_NAME args none | ARGS_BYTE_ARRAY [ const ]
488 * instanceof TABLE_TYPE_NAME
495 struct rte_swx_pipeline_table_params params;
496 char *recommended_table_type_name;
502 table_spec_free(struct table_spec *s)
504 uintptr_t default_action_name;
513 for (i = 0; i < s->params.n_fields; i++) {
514 uintptr_t name = (uintptr_t)s->params.fields[i].name;
519 free(s->params.fields);
520 s->params.fields = NULL;
522 s->params.n_fields = 0;
524 for (i = 0; i < s->params.n_actions; i++) {
525 uintptr_t name = (uintptr_t)s->params.action_names[i];
530 free(s->params.action_names);
531 s->params.action_names = NULL;
533 s->params.n_actions = 0;
535 default_action_name = (uintptr_t)s->params.default_action_name;
536 free((void *)default_action_name);
537 s->params.default_action_name = NULL;
539 free(s->params.default_action_data);
540 s->params.default_action_data = NULL;
542 s->params.default_action_is_const = 0;
544 free(s->recommended_table_type_name);
545 s->recommended_table_type_name = NULL;
554 table_key_statement_parse(uint32_t *block_mask,
559 const char **err_msg)
562 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
566 *err_msg = "Invalid key statement.";
571 *block_mask |= 1 << TABLE_KEY_BLOCK;
577 table_key_block_parse(struct table_spec *s,
578 uint32_t *block_mask,
583 const char **err_msg)
585 struct rte_swx_match_field_params *new_fields;
586 enum rte_swx_table_match_type match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
589 /* Handle end of block. */
590 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
591 *block_mask &= ~(1 << TABLE_KEY_BLOCK);
595 /* Check input arguments. */
596 if ((n_tokens != 2) ||
597 (strcmp(tokens[1], "exact") &&
598 strcmp(tokens[1], "wildcard") &&
599 strcmp(tokens[1], "lpm"))) {
603 *err_msg = "Invalid match field statement.";
607 if (!strcmp(tokens[1], "wildcard"))
608 match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
609 if (!strcmp(tokens[1], "lpm"))
610 match_type = RTE_SWX_TABLE_MATCH_LPM;
611 if (!strcmp(tokens[1], "exact"))
612 match_type = RTE_SWX_TABLE_MATCH_EXACT;
614 name = strdup(tokens[0]);
619 *err_msg = "Memory allocation failed.";
623 new_fields = reallocarray(s->params.fields,
624 s->params.n_fields + 1,
625 sizeof(struct rte_swx_match_field_params));
632 *err_msg = "Memory allocation failed.";
636 s->params.fields = new_fields;
637 s->params.fields[s->params.n_fields].name = name;
638 s->params.fields[s->params.n_fields].match_type = match_type;
639 s->params.n_fields++;
645 table_actions_statement_parse(uint32_t *block_mask,
650 const char **err_msg)
653 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
657 *err_msg = "Invalid actions statement.";
662 *block_mask |= 1 << TABLE_ACTIONS_BLOCK;
668 table_actions_block_parse(struct table_spec *s,
669 uint32_t *block_mask,
674 const char **err_msg)
676 const char **new_action_names;
679 /* Handle end of block. */
680 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
681 *block_mask &= ~(1 << TABLE_ACTIONS_BLOCK);
685 /* Check input arguments. */
690 *err_msg = "Invalid action name statement.";
694 name = strdup(tokens[0]);
699 *err_msg = "Memory allocation failed.";
703 new_action_names = reallocarray(s->params.action_names,
704 s->params.n_actions + 1,
706 if (!new_action_names) {
712 *err_msg = "Memory allocation failed.";
716 s->params.action_names = new_action_names;
717 s->params.action_names[s->params.n_actions] = name;
718 s->params.n_actions++;
724 table_statement_parse(struct table_spec *s,
725 uint32_t *block_mask,
730 const char **err_msg)
733 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
737 *err_msg = "Invalid table statement.";
742 s->name = strdup(tokens[1]);
747 *err_msg = "Memory allocation failed.";
752 *block_mask |= 1 << TABLE_BLOCK;
758 table_block_parse(struct table_spec *s,
759 uint32_t *block_mask,
764 const char **err_msg)
766 if (*block_mask & (1 << TABLE_KEY_BLOCK))
767 return table_key_block_parse(s,
775 if (*block_mask & (1 << TABLE_ACTIONS_BLOCK))
776 return table_actions_block_parse(s,
784 /* Handle end of block. */
785 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
786 *block_mask &= ~(1 << TABLE_BLOCK);
790 if (!strcmp(tokens[0], "key"))
791 return table_key_statement_parse(block_mask,
798 if (!strcmp(tokens[0], "actions"))
799 return table_actions_statement_parse(block_mask,
806 if (!strcmp(tokens[0], "default_action")) {
807 if (((n_tokens != 4) && (n_tokens != 5)) ||
808 strcmp(tokens[2], "args") ||
809 strcmp(tokens[3], "none") ||
810 ((n_tokens == 5) && strcmp(tokens[4], "const"))) {
814 *err_msg = "Invalid default_action statement.";
818 if (s->params.default_action_name) {
822 *err_msg = "Duplicate default_action stmt.";
826 s->params.default_action_name = strdup(tokens[1]);
827 if (!s->params.default_action_name) {
831 *err_msg = "Memory allocation failed.";
836 s->params.default_action_is_const = 1;
841 if (!strcmp(tokens[0], "instanceof")) {
846 *err_msg = "Invalid instanceof statement.";
850 if (s->recommended_table_type_name) {
854 *err_msg = "Duplicate instanceof statement.";
858 s->recommended_table_type_name = strdup(tokens[1]);
859 if (!s->recommended_table_type_name) {
863 *err_msg = "Memory allocation failed.";
870 if (!strcmp(tokens[0], "pragma")) {
875 *err_msg = "Invalid pragma statement.";
883 *err_msg = "Duplicate pragma statement.";
887 s->args = strdup(tokens[1]);
892 *err_msg = "Memory allocation failed.";
899 if (!strcmp(tokens[0], "size")) {
906 *err_msg = "Invalid pragma statement.";
910 s->size = strtoul(p, &p, 0);
915 *err_msg = "Invalid size argument.";
926 *err_msg = "Invalid statement.";
939 const char **instructions;
940 uint32_t n_instructions;
944 apply_spec_free(struct apply_spec *s)
951 for (i = 0; i < s->n_instructions; i++) {
952 uintptr_t instr = (uintptr_t)s->instructions[i];
957 free(s->instructions);
958 s->instructions = NULL;
960 s->n_instructions = 0;
964 apply_statement_parse(uint32_t *block_mask,
969 const char **err_msg)
972 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
976 *err_msg = "Invalid apply statement.";
981 *block_mask |= 1 << APPLY_BLOCK;
987 apply_block_parse(struct apply_spec *s,
988 uint32_t *block_mask,
993 const char **err_msg)
995 char buffer[MAX_INSTRUCTION_LENGTH], *instr;
996 const char **new_instructions;
999 /* Handle end of block. */
1000 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1001 *block_mask &= ~(1 << APPLY_BLOCK);
1007 for (i = 0; i < n_tokens; i++) {
1009 strcat(buffer, " ");
1010 strcat(buffer, tokens[i]);
1013 instr = strdup(buffer);
1016 *err_line = n_lines;
1018 *err_msg = "Memory allocation failed.";
1022 new_instructions = reallocarray(s->instructions,
1023 s->n_instructions + 1,
1025 if (!new_instructions) {
1029 *err_line = n_lines;
1031 *err_msg = "Memory allocation failed.";
1035 s->instructions = new_instructions;
1036 s->instructions[s->n_instructions] = instr;
1037 s->n_instructions++;
1046 rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
1049 const char **err_msg)
1051 struct extobj_spec extobj_spec = {0};
1052 struct struct_spec struct_spec = {0};
1053 struct header_spec header_spec = {0};
1054 struct metadata_spec metadata_spec = {0};
1055 struct action_spec action_spec = {0};
1056 struct table_spec table_spec = {0};
1057 struct apply_spec apply_spec = {0};
1059 uint32_t block_mask = 0;
1062 /* Check the input arguments. */
1067 *err_msg = "Null pipeline arument.";
1076 *err_msg = "Null specification file argument.";
1081 for (n_lines = 1; ; n_lines++) {
1082 char line[MAX_LINE_LENGTH];
1083 char *tokens[MAX_TOKENS], *ptr = line;
1084 uint32_t n_tokens = 0;
1086 /* Read next line. */
1087 if (!fgets(line, sizeof(line), spec))
1090 /* Parse the line into tokens. */
1095 token = strtok_r(ptr, " \f\n\r\t\v", &ptr);
1099 /* Handle comments. */
1100 if ((token[0] == '#') ||
1101 (token[0] == ';') ||
1102 ((token[0] == '/') && (token[1] == '/'))) {
1106 /* Handle excessively long lines. */
1107 if (n_tokens >= MAX_TOKENS) {
1109 *err_line = n_lines;
1111 *err_msg = "Too many tokens.";
1117 tokens[n_tokens] = token;
1121 /* Handle empty lines. */
1126 if (block_mask & (1 << STRUCT_BLOCK)) {
1127 status = struct_block_parse(&struct_spec,
1137 if (block_mask & (1 << STRUCT_BLOCK))
1141 status = rte_swx_pipeline_struct_type_register(p,
1144 struct_spec.n_fields);
1147 *err_line = n_lines;
1149 *err_msg = "Struct registration error.";
1153 struct_spec_free(&struct_spec);
1159 if (block_mask & (1 << ACTION_BLOCK)) {
1160 status = action_block_parse(&action_spec,
1170 if (block_mask & (1 << ACTION_BLOCK))
1174 status = rte_swx_pipeline_action_config(p,
1176 action_spec.args_struct_type_name,
1177 action_spec.instructions,
1178 action_spec.n_instructions);
1181 *err_line = n_lines;
1183 *err_msg = "Action config error.";
1187 action_spec_free(&action_spec);
1193 if (block_mask & (1 << TABLE_BLOCK)) {
1194 status = table_block_parse(&table_spec,
1204 if (block_mask & (1 << TABLE_BLOCK))
1208 status = rte_swx_pipeline_table_config(p,
1211 table_spec.recommended_table_type_name,
1216 *err_line = n_lines;
1218 *err_msg = "Table configuration error.";
1222 table_spec_free(&table_spec);
1228 if (block_mask & (1 << APPLY_BLOCK)) {
1229 status = apply_block_parse(&apply_spec,
1239 if (block_mask & (1 << APPLY_BLOCK))
1243 status = rte_swx_pipeline_instructions_config(p,
1244 apply_spec.instructions,
1245 apply_spec.n_instructions);
1248 *err_line = n_lines;
1250 *err_msg = "Pipeline instructions err.";
1254 apply_spec_free(&apply_spec);
1260 if (!strcmp(tokens[0], "extobj")) {
1261 status = extobj_statement_parse(&extobj_spec,
1270 status = rte_swx_pipeline_extern_object_config(p,
1272 extobj_spec.extern_type_name,
1273 extobj_spec.pragma);
1276 *err_line = n_lines;
1278 *err_msg = "Extern object config err.";
1282 extobj_spec_free(&extobj_spec);
1288 if (!strcmp(tokens[0], "struct")) {
1289 status = struct_statement_parse(&struct_spec,
1303 if (!strcmp(tokens[0], "header")) {
1304 status = header_statement_parse(&header_spec,
1313 status = rte_swx_pipeline_packet_header_register(p,
1315 header_spec.struct_type_name);
1318 *err_line = n_lines;
1320 *err_msg = "Header registration error.";
1324 header_spec_free(&header_spec);
1330 if (!strcmp(tokens[0], "metadata")) {
1331 status = metadata_statement_parse(&metadata_spec,
1340 status = rte_swx_pipeline_packet_metadata_register(p,
1341 metadata_spec.struct_type_name);
1344 *err_line = n_lines;
1346 *err_msg = "Meta-data reg err.";
1350 metadata_spec_free(&metadata_spec);
1356 if (!strcmp(tokens[0], "action")) {
1357 status = action_statement_parse(&action_spec,
1371 if (!strcmp(tokens[0], "table")) {
1372 status = table_statement_parse(&table_spec,
1386 if (!strcmp(tokens[0], "apply")) {
1387 status = apply_statement_parse(&block_mask,
1399 /* Anything else. */
1401 *err_line = n_lines;
1403 *err_msg = "Unknown statement.";
1408 /* Handle unfinished block. */
1411 *err_line = n_lines;
1413 *err_msg = "Missing }.";
1418 /* Pipeline build. */
1419 status = rte_swx_pipeline_build(p);
1422 *err_line = n_lines;
1424 *err_msg = "Pipeline build error.";
1431 extobj_spec_free(&extobj_spec);
1432 struct_spec_free(&struct_spec);
1433 header_spec_free(&header_spec);
1434 metadata_spec_free(&metadata_spec);
1435 action_spec_free(&action_spec);
1436 table_spec_free(&table_spec);
1437 apply_spec_free(&apply_spec);