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)
44 free(s->extern_type_name);
45 s->extern_type_name = NULL;
52 extobj_statement_parse(struct extobj_spec *s,
60 if (((n_tokens != 4) && (n_tokens != 6)) ||
61 ((n_tokens == 4) && strcmp(tokens[2], "instanceof")) ||
62 ((n_tokens == 6) && (strcmp(tokens[2], "instanceof") ||
63 strcmp(tokens[4], "pragma")))) {
67 *err_msg = "Invalid extobj statement.";
72 s->name = strdup(tokens[1]);
73 s->extern_type_name = strdup(tokens[3]);
74 s->pragma = (n_tokens == 6) ? strdup(tokens[5]) : NULL;
77 !s->extern_type_name ||
78 ((n_tokens == 6) && !s->pragma)) {
80 free(s->extern_type_name);
86 *err_msg = "Memory allocation failed.";
96 * struct STRUCT_TYPE_NAME {
97 * bit<SIZE> FIELD_NAME
103 struct rte_swx_field_params *fields;
108 struct_spec_free(struct struct_spec *s)
118 for (i = 0; i < s->n_fields; i++) {
119 uintptr_t name = (uintptr_t)s->fields[i].name;
131 struct_statement_parse(struct struct_spec *s,
132 uint32_t *block_mask,
137 const char **err_msg)
140 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
144 *err_msg = "Invalid struct statement.";
149 s->name = strdup(tokens[1]);
154 *err_msg = "Memory allocation failed.";
159 *block_mask |= 1 << STRUCT_BLOCK;
165 struct_block_parse(struct struct_spec *s,
166 uint32_t *block_mask,
171 const char **err_msg)
173 struct rte_swx_field_params *new_fields;
174 char *p = tokens[0], *name;
177 /* Handle end of block. */
178 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
179 *block_mask &= ~(1 << STRUCT_BLOCK);
184 if ((n_tokens != 2) ||
190 (p[strlen(p) - 1] != '>')) {
194 *err_msg = "Invalid struct field statement.";
198 /* Remove the "bit<" and ">". */
199 p[strlen(p) - 1] = 0;
202 n_bits = strtoul(p, &p, 0);
210 *err_msg = "Invalid struct field size.";
215 name = strdup(tokens[1]);
220 *err_msg = "Memory allocation failed.";
224 new_fields = realloc(s->fields,
225 (s->n_fields + 1) * sizeof(struct rte_swx_field_params));
232 *err_msg = "Memory allocation failed.";
236 s->fields = new_fields;
237 s->fields[s->n_fields].name = name;
238 s->fields[s->n_fields].n_bits = n_bits;
247 * header HEADER_NAME instanceof STRUCT_TYPE_NAME
251 char *struct_type_name;
255 header_spec_free(struct header_spec *s)
263 free(s->struct_type_name);
264 s->struct_type_name = NULL;
268 header_statement_parse(struct header_spec *s,
273 const char **err_msg)
276 if ((n_tokens != 4) || strcmp(tokens[2], "instanceof")) {
280 *err_msg = "Invalid header statement.";
285 s->name = strdup(tokens[1]);
286 s->struct_type_name = strdup(tokens[3]);
288 if (!s->name || !s->struct_type_name) {
290 free(s->struct_type_name);
295 *err_msg = "Memory allocation failed.";
305 * metadata instanceof STRUCT_TYPE_NAME
307 struct metadata_spec {
308 char *struct_type_name;
312 metadata_spec_free(struct metadata_spec *s)
317 free(s->struct_type_name);
318 s->struct_type_name = NULL;
322 metadata_statement_parse(struct metadata_spec *s,
327 const char **err_msg)
330 if ((n_tokens != 3) || strcmp(tokens[1], "instanceof")) {
334 *err_msg = "Invalid metadata statement.";
339 s->struct_type_name = strdup(tokens[2]);
340 if (!s->struct_type_name) {
344 *err_msg = "Memory allocation failed.";
354 * action ACTION_NAME args none | instanceof STRUCT_TYPE_NAME {
361 char *args_struct_type_name;
362 const char **instructions;
363 uint32_t n_instructions;
367 action_spec_free(struct action_spec *s)
377 free(s->args_struct_type_name);
378 s->args_struct_type_name = NULL;
380 for (i = 0; i < s->n_instructions; i++) {
381 uintptr_t instr = (uintptr_t)s->instructions[i];
386 free(s->instructions);
387 s->instructions = NULL;
389 s->n_instructions = 0;
393 action_statement_parse(struct action_spec *s,
394 uint32_t *block_mask,
399 const char **err_msg)
402 if (((n_tokens != 5) && (n_tokens != 6)) ||
404 (strcmp(tokens[2], "args") ||
405 strcmp(tokens[3], "none") ||
406 strcmp(tokens[4], "{"))) ||
408 (strcmp(tokens[2], "args") ||
409 strcmp(tokens[3], "instanceof") ||
410 strcmp(tokens[5], "{")))) {
414 *err_msg = "Invalid action statement.";
419 s->name = strdup(tokens[1]);
420 s->args_struct_type_name = (n_tokens == 6) ? strdup(tokens[4]) : NULL;
422 if ((!s->name) || ((n_tokens == 6) && !s->args_struct_type_name)) {
426 *err_msg = "Memory allocation failed.";
431 *block_mask |= 1 << ACTION_BLOCK;
437 action_block_parse(struct action_spec *s,
438 uint32_t *block_mask,
443 const char **err_msg)
445 char buffer[MAX_INSTRUCTION_LENGTH], *instr;
446 const char **new_instructions;
449 /* Handle end of block. */
450 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
451 *block_mask &= ~(1 << ACTION_BLOCK);
457 for (i = 0; i < n_tokens; i++) {
460 strcat(buffer, tokens[i]);
463 instr = strdup(buffer);
468 *err_msg = "Memory allocation failed.";
472 new_instructions = realloc(s->instructions,
473 (s->n_instructions + 1) * sizeof(char *));
474 if (!new_instructions) {
480 *err_msg = "Memory allocation failed.";
484 s->instructions = new_instructions;
485 s->instructions[s->n_instructions] = instr;
496 * MATCH_FIELD_NAME exact | wildcard | lpm
503 * default_action ACTION_NAME args none | ARGS_BYTE_ARRAY [ const ]
504 * instanceof TABLE_TYPE_NAME
511 struct rte_swx_pipeline_table_params params;
512 char *recommended_table_type_name;
518 table_spec_free(struct table_spec *s)
520 uintptr_t default_action_name;
529 for (i = 0; i < s->params.n_fields; i++) {
530 uintptr_t name = (uintptr_t)s->params.fields[i].name;
535 free(s->params.fields);
536 s->params.fields = NULL;
538 s->params.n_fields = 0;
540 for (i = 0; i < s->params.n_actions; i++) {
541 uintptr_t name = (uintptr_t)s->params.action_names[i];
546 free(s->params.action_names);
547 s->params.action_names = NULL;
549 s->params.n_actions = 0;
551 default_action_name = (uintptr_t)s->params.default_action_name;
552 free((void *)default_action_name);
553 s->params.default_action_name = NULL;
555 free(s->params.default_action_data);
556 s->params.default_action_data = NULL;
558 s->params.default_action_is_const = 0;
560 free(s->recommended_table_type_name);
561 s->recommended_table_type_name = NULL;
570 table_key_statement_parse(uint32_t *block_mask,
575 const char **err_msg)
578 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
582 *err_msg = "Invalid key statement.";
587 *block_mask |= 1 << TABLE_KEY_BLOCK;
593 table_key_block_parse(struct table_spec *s,
594 uint32_t *block_mask,
599 const char **err_msg)
601 struct rte_swx_match_field_params *new_fields;
602 enum rte_swx_table_match_type match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
605 /* Handle end of block. */
606 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
607 *block_mask &= ~(1 << TABLE_KEY_BLOCK);
611 /* Check input arguments. */
612 if ((n_tokens != 2) ||
613 (strcmp(tokens[1], "exact") &&
614 strcmp(tokens[1], "wildcard") &&
615 strcmp(tokens[1], "lpm"))) {
619 *err_msg = "Invalid match field statement.";
623 if (!strcmp(tokens[1], "wildcard"))
624 match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
625 if (!strcmp(tokens[1], "lpm"))
626 match_type = RTE_SWX_TABLE_MATCH_LPM;
627 if (!strcmp(tokens[1], "exact"))
628 match_type = RTE_SWX_TABLE_MATCH_EXACT;
630 name = strdup(tokens[0]);
635 *err_msg = "Memory allocation failed.";
639 new_fields = realloc(s->params.fields,
640 (s->params.n_fields + 1) * sizeof(struct rte_swx_match_field_params));
647 *err_msg = "Memory allocation failed.";
651 s->params.fields = new_fields;
652 s->params.fields[s->params.n_fields].name = name;
653 s->params.fields[s->params.n_fields].match_type = match_type;
654 s->params.n_fields++;
660 table_actions_statement_parse(uint32_t *block_mask,
665 const char **err_msg)
668 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
672 *err_msg = "Invalid actions statement.";
677 *block_mask |= 1 << TABLE_ACTIONS_BLOCK;
683 table_actions_block_parse(struct table_spec *s,
684 uint32_t *block_mask,
689 const char **err_msg)
691 const char **new_action_names;
694 /* Handle end of block. */
695 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
696 *block_mask &= ~(1 << TABLE_ACTIONS_BLOCK);
700 /* Check input arguments. */
705 *err_msg = "Invalid action name statement.";
709 name = strdup(tokens[0]);
714 *err_msg = "Memory allocation failed.";
718 new_action_names = realloc(s->params.action_names,
719 (s->params.n_actions + 1) * sizeof(char *));
720 if (!new_action_names) {
726 *err_msg = "Memory allocation failed.";
730 s->params.action_names = new_action_names;
731 s->params.action_names[s->params.n_actions] = name;
732 s->params.n_actions++;
738 table_statement_parse(struct table_spec *s,
739 uint32_t *block_mask,
744 const char **err_msg)
747 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
751 *err_msg = "Invalid table statement.";
756 s->name = strdup(tokens[1]);
761 *err_msg = "Memory allocation failed.";
766 *block_mask |= 1 << TABLE_BLOCK;
772 table_block_parse(struct table_spec *s,
773 uint32_t *block_mask,
778 const char **err_msg)
780 if (*block_mask & (1 << TABLE_KEY_BLOCK))
781 return table_key_block_parse(s,
789 if (*block_mask & (1 << TABLE_ACTIONS_BLOCK))
790 return table_actions_block_parse(s,
798 /* Handle end of block. */
799 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
800 *block_mask &= ~(1 << TABLE_BLOCK);
804 if (!strcmp(tokens[0], "key"))
805 return table_key_statement_parse(block_mask,
812 if (!strcmp(tokens[0], "actions"))
813 return table_actions_statement_parse(block_mask,
820 if (!strcmp(tokens[0], "default_action")) {
821 if (((n_tokens != 4) && (n_tokens != 5)) ||
822 strcmp(tokens[2], "args") ||
823 strcmp(tokens[3], "none") ||
824 ((n_tokens == 5) && strcmp(tokens[4], "const"))) {
828 *err_msg = "Invalid default_action statement.";
832 if (s->params.default_action_name) {
836 *err_msg = "Duplicate default_action stmt.";
840 s->params.default_action_name = strdup(tokens[1]);
841 if (!s->params.default_action_name) {
845 *err_msg = "Memory allocation failed.";
850 s->params.default_action_is_const = 1;
855 if (!strcmp(tokens[0], "instanceof")) {
860 *err_msg = "Invalid instanceof statement.";
864 if (s->recommended_table_type_name) {
868 *err_msg = "Duplicate instanceof statement.";
872 s->recommended_table_type_name = strdup(tokens[1]);
873 if (!s->recommended_table_type_name) {
877 *err_msg = "Memory allocation failed.";
884 if (!strcmp(tokens[0], "pragma")) {
889 *err_msg = "Invalid pragma statement.";
897 *err_msg = "Duplicate pragma statement.";
901 s->args = strdup(tokens[1]);
906 *err_msg = "Memory allocation failed.";
913 if (!strcmp(tokens[0], "size")) {
920 *err_msg = "Invalid pragma statement.";
924 s->size = strtoul(p, &p, 0);
929 *err_msg = "Invalid size argument.";
940 *err_msg = "Invalid statement.";
953 const char **instructions;
954 uint32_t n_instructions;
958 apply_spec_free(struct apply_spec *s)
965 for (i = 0; i < s->n_instructions; i++) {
966 uintptr_t instr = (uintptr_t)s->instructions[i];
971 free(s->instructions);
972 s->instructions = NULL;
974 s->n_instructions = 0;
978 apply_statement_parse(uint32_t *block_mask,
983 const char **err_msg)
986 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
990 *err_msg = "Invalid apply statement.";
995 *block_mask |= 1 << APPLY_BLOCK;
1001 apply_block_parse(struct apply_spec *s,
1002 uint32_t *block_mask,
1007 const char **err_msg)
1009 char buffer[MAX_INSTRUCTION_LENGTH], *instr;
1010 const char **new_instructions;
1013 /* Handle end of block. */
1014 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1015 *block_mask &= ~(1 << APPLY_BLOCK);
1021 for (i = 0; i < n_tokens; i++) {
1023 strcat(buffer, " ");
1024 strcat(buffer, tokens[i]);
1027 instr = strdup(buffer);
1030 *err_line = n_lines;
1032 *err_msg = "Memory allocation failed.";
1036 new_instructions = realloc(s->instructions,
1037 (s->n_instructions + 1) * sizeof(char *));
1038 if (!new_instructions) {
1042 *err_line = n_lines;
1044 *err_msg = "Memory allocation failed.";
1048 s->instructions = new_instructions;
1049 s->instructions[s->n_instructions] = instr;
1050 s->n_instructions++;
1059 rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
1062 const char **err_msg)
1064 struct extobj_spec extobj_spec = {0};
1065 struct struct_spec struct_spec = {0};
1066 struct header_spec header_spec = {0};
1067 struct metadata_spec metadata_spec = {0};
1068 struct action_spec action_spec = {0};
1069 struct table_spec table_spec = {0};
1070 struct apply_spec apply_spec = {0};
1072 uint32_t block_mask = 0;
1075 /* Check the input arguments. */
1080 *err_msg = "Null pipeline arument.";
1089 *err_msg = "Null specification file argument.";
1094 for (n_lines = 1; ; n_lines++) {
1095 char line[MAX_LINE_LENGTH];
1096 char *tokens[MAX_TOKENS], *ptr = line;
1097 uint32_t n_tokens = 0;
1099 /* Read next line. */
1100 if (!fgets(line, sizeof(line), spec))
1103 /* Parse the line into tokens. */
1108 token = strtok_r(ptr, " \f\n\r\t\v", &ptr);
1112 /* Handle comments. */
1113 if ((token[0] == '#') ||
1114 (token[0] == ';') ||
1115 ((token[0] == '/') && (token[1] == '/'))) {
1119 /* Handle excessively long lines. */
1120 if (n_tokens >= MAX_TOKENS) {
1122 *err_line = n_lines;
1124 *err_msg = "Too many tokens.";
1130 tokens[n_tokens] = token;
1134 /* Handle empty lines. */
1139 if (block_mask & (1 << STRUCT_BLOCK)) {
1140 status = struct_block_parse(&struct_spec,
1150 if (block_mask & (1 << STRUCT_BLOCK))
1154 status = rte_swx_pipeline_struct_type_register(p,
1157 struct_spec.n_fields);
1160 *err_line = n_lines;
1162 *err_msg = "Struct registration error.";
1166 struct_spec_free(&struct_spec);
1172 if (block_mask & (1 << ACTION_BLOCK)) {
1173 status = action_block_parse(&action_spec,
1183 if (block_mask & (1 << ACTION_BLOCK))
1187 status = rte_swx_pipeline_action_config(p,
1189 action_spec.args_struct_type_name,
1190 action_spec.instructions,
1191 action_spec.n_instructions);
1194 *err_line = n_lines;
1196 *err_msg = "Action config error.";
1200 action_spec_free(&action_spec);
1206 if (block_mask & (1 << TABLE_BLOCK)) {
1207 status = table_block_parse(&table_spec,
1217 if (block_mask & (1 << TABLE_BLOCK))
1221 status = rte_swx_pipeline_table_config(p,
1224 table_spec.recommended_table_type_name,
1229 *err_line = n_lines;
1231 *err_msg = "Table configuration error.";
1235 table_spec_free(&table_spec);
1241 if (block_mask & (1 << APPLY_BLOCK)) {
1242 status = apply_block_parse(&apply_spec,
1252 if (block_mask & (1 << APPLY_BLOCK))
1256 status = rte_swx_pipeline_instructions_config(p,
1257 apply_spec.instructions,
1258 apply_spec.n_instructions);
1261 *err_line = n_lines;
1263 *err_msg = "Pipeline instructions err.";
1267 apply_spec_free(&apply_spec);
1273 if (!strcmp(tokens[0], "extobj")) {
1274 status = extobj_statement_parse(&extobj_spec,
1283 status = rte_swx_pipeline_extern_object_config(p,
1285 extobj_spec.extern_type_name,
1286 extobj_spec.pragma);
1289 *err_line = n_lines;
1291 *err_msg = "Extern object config err.";
1295 extobj_spec_free(&extobj_spec);
1301 if (!strcmp(tokens[0], "struct")) {
1302 status = struct_statement_parse(&struct_spec,
1316 if (!strcmp(tokens[0], "header")) {
1317 status = header_statement_parse(&header_spec,
1326 status = rte_swx_pipeline_packet_header_register(p,
1328 header_spec.struct_type_name);
1331 *err_line = n_lines;
1333 *err_msg = "Header registration error.";
1337 header_spec_free(&header_spec);
1343 if (!strcmp(tokens[0], "metadata")) {
1344 status = metadata_statement_parse(&metadata_spec,
1353 status = rte_swx_pipeline_packet_metadata_register(p,
1354 metadata_spec.struct_type_name);
1357 *err_line = n_lines;
1359 *err_msg = "Meta-data reg err.";
1363 metadata_spec_free(&metadata_spec);
1369 if (!strcmp(tokens[0], "action")) {
1370 status = action_statement_parse(&action_spec,
1384 if (!strcmp(tokens[0], "table")) {
1385 status = table_statement_parse(&table_spec,
1399 if (!strcmp(tokens[0], "apply")) {
1400 status = apply_statement_parse(&block_mask,
1412 /* Anything else. */
1414 *err_line = n_lines;
1416 *err_msg = "Unknown statement.";
1421 /* Handle unfinished block. */
1424 *err_line = n_lines;
1426 *err_msg = "Missing }.";
1431 /* Pipeline build. */
1432 status = rte_swx_pipeline_build(p);
1435 *err_line = n_lines;
1437 *err_msg = "Pipeline build error.";
1444 extobj_spec_free(&extobj_spec);
1445 struct_spec_free(&struct_spec);
1446 header_spec_free(&header_spec);
1447 metadata_spec_free(&metadata_spec);
1448 action_spec_free(&action_spec);
1449 table_spec_free(&table_spec);
1450 apply_spec_free(&apply_spec);