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
26 * extobj OBJ_NAME instanceof OBJ_TYPE [ pragma OBJ_CREATE_ARGS ]
30 char *extern_type_name;
35 extobj_spec_free(struct extobj_spec *s)
43 free(s->extern_type_name);
44 s->extern_type_name = NULL;
51 extobj_statement_parse(struct extobj_spec *s,
59 if (((n_tokens != 4) && (n_tokens != 6)) ||
60 ((n_tokens == 4) && strcmp(tokens[2], "instanceof")) ||
61 ((n_tokens == 6) && (strcmp(tokens[2], "instanceof") ||
62 strcmp(tokens[4], "pragma")))) {
66 *err_msg = "Invalid extobj statement.";
71 s->name = strdup(tokens[1]);
72 s->extern_type_name = strdup(tokens[3]);
73 s->pragma = (n_tokens == 6) ? strdup(tokens[5]) : NULL;
76 !s->extern_type_name ||
77 ((n_tokens == 6) && !s->pragma)) {
79 free(s->extern_type_name);
85 *err_msg = "Memory allocation failed.";
95 * struct STRUCT_TYPE_NAME {
96 * bit<SIZE> FIELD_NAME
102 struct rte_swx_field_params *fields;
107 struct_spec_free(struct struct_spec *s)
117 for (i = 0; i < s->n_fields; i++) {
118 uintptr_t name = (uintptr_t)s->fields[i].name;
130 struct_statement_parse(struct struct_spec *s,
131 uint32_t *block_mask,
136 const char **err_msg)
139 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
143 *err_msg = "Invalid struct statement.";
148 s->name = strdup(tokens[1]);
153 *err_msg = "Memory allocation failed.";
158 *block_mask |= 1 << STRUCT_BLOCK;
164 struct_block_parse(struct struct_spec *s,
165 uint32_t *block_mask,
170 const char **err_msg)
172 struct rte_swx_field_params *new_fields;
173 char *p = tokens[0], *name;
176 /* Handle end of block. */
177 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
178 *block_mask &= ~(1 << STRUCT_BLOCK);
183 if ((n_tokens != 2) ||
189 (p[strlen(p) - 1] != '>')) {
193 *err_msg = "Invalid struct field statement.";
197 /* Remove the "bit<" and ">". */
198 p[strlen(p) - 1] = 0;
201 n_bits = strtoul(p, &p, 0);
209 *err_msg = "Invalid struct field size.";
214 name = strdup(tokens[1]);
219 *err_msg = "Memory allocation failed.";
223 new_fields = realloc(s->fields,
224 (s->n_fields + 1) * sizeof(struct rte_swx_field_params));
231 *err_msg = "Memory allocation failed.";
235 s->fields = new_fields;
236 s->fields[s->n_fields].name = name;
237 s->fields[s->n_fields].n_bits = n_bits;
246 * header HEADER_NAME instanceof STRUCT_TYPE_NAME
250 char *struct_type_name;
254 header_spec_free(struct header_spec *s)
262 free(s->struct_type_name);
263 s->struct_type_name = NULL;
267 header_statement_parse(struct header_spec *s,
272 const char **err_msg)
275 if ((n_tokens != 4) || strcmp(tokens[2], "instanceof")) {
279 *err_msg = "Invalid header statement.";
284 s->name = strdup(tokens[1]);
285 s->struct_type_name = strdup(tokens[3]);
287 if (!s->name || !s->struct_type_name) {
289 free(s->struct_type_name);
294 *err_msg = "Memory allocation failed.";
304 * metadata instanceof STRUCT_TYPE_NAME
306 struct metadata_spec {
307 char *struct_type_name;
311 metadata_spec_free(struct metadata_spec *s)
316 free(s->struct_type_name);
317 s->struct_type_name = NULL;
321 metadata_statement_parse(struct metadata_spec *s,
326 const char **err_msg)
329 if ((n_tokens != 3) || strcmp(tokens[1], "instanceof")) {
333 *err_msg = "Invalid metadata statement.";
338 s->struct_type_name = strdup(tokens[2]);
339 if (!s->struct_type_name) {
343 *err_msg = "Memory allocation failed.";
353 * action ACTION_NAME args none | instanceof STRUCT_TYPE_NAME {
360 char *args_struct_type_name;
361 const char **instructions;
362 uint32_t n_instructions;
366 action_spec_free(struct action_spec *s)
376 free(s->args_struct_type_name);
377 s->args_struct_type_name = NULL;
379 for (i = 0; i < s->n_instructions; i++) {
380 uintptr_t instr = (uintptr_t)s->instructions[i];
385 free(s->instructions);
386 s->instructions = NULL;
388 s->n_instructions = 0;
392 action_statement_parse(struct action_spec *s,
393 uint32_t *block_mask,
398 const char **err_msg)
401 if (((n_tokens != 5) && (n_tokens != 6)) ||
403 (strcmp(tokens[2], "args") ||
404 strcmp(tokens[3], "none") ||
405 strcmp(tokens[4], "{"))) ||
407 (strcmp(tokens[2], "args") ||
408 strcmp(tokens[3], "instanceof") ||
409 strcmp(tokens[5], "{")))) {
413 *err_msg = "Invalid action statement.";
418 s->name = strdup(tokens[1]);
419 s->args_struct_type_name = (n_tokens == 6) ? strdup(tokens[4]) : NULL;
421 if ((!s->name) || ((n_tokens == 6) && !s->args_struct_type_name)) {
425 *err_msg = "Memory allocation failed.";
430 *block_mask |= 1 << ACTION_BLOCK;
436 action_block_parse(struct action_spec *s,
437 uint32_t *block_mask,
442 const char **err_msg)
444 char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr;
445 const char **new_instructions;
448 /* Handle end of block. */
449 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
450 *block_mask &= ~(1 << ACTION_BLOCK);
456 for (i = 0; i < n_tokens; i++) {
459 strcat(buffer, tokens[i]);
462 instr = strdup(buffer);
467 *err_msg = "Memory allocation failed.";
471 new_instructions = realloc(s->instructions,
472 (s->n_instructions + 1) * sizeof(char *));
473 if (!new_instructions) {
479 *err_msg = "Memory allocation failed.";
483 s->instructions = new_instructions;
484 s->instructions[s->n_instructions] = instr;
495 * MATCH_FIELD_NAME exact | wildcard | lpm
502 * default_action ACTION_NAME args none | ARGS_BYTE_ARRAY [ const ]
503 * instanceof TABLE_TYPE_NAME
510 struct rte_swx_pipeline_table_params params;
511 char *recommended_table_type_name;
517 table_spec_free(struct table_spec *s)
519 uintptr_t default_action_name;
528 for (i = 0; i < s->params.n_fields; i++) {
529 uintptr_t name = (uintptr_t)s->params.fields[i].name;
534 free(s->params.fields);
535 s->params.fields = NULL;
537 s->params.n_fields = 0;
539 for (i = 0; i < s->params.n_actions; i++) {
540 uintptr_t name = (uintptr_t)s->params.action_names[i];
545 free(s->params.action_names);
546 s->params.action_names = NULL;
548 s->params.n_actions = 0;
550 default_action_name = (uintptr_t)s->params.default_action_name;
551 free((void *)default_action_name);
552 s->params.default_action_name = NULL;
554 free(s->params.default_action_data);
555 s->params.default_action_data = NULL;
557 s->params.default_action_is_const = 0;
559 free(s->recommended_table_type_name);
560 s->recommended_table_type_name = NULL;
569 table_key_statement_parse(uint32_t *block_mask,
574 const char **err_msg)
577 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
581 *err_msg = "Invalid key statement.";
586 *block_mask |= 1 << TABLE_KEY_BLOCK;
592 table_key_block_parse(struct table_spec *s,
593 uint32_t *block_mask,
598 const char **err_msg)
600 struct rte_swx_match_field_params *new_fields;
601 enum rte_swx_table_match_type match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
604 /* Handle end of block. */
605 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
606 *block_mask &= ~(1 << TABLE_KEY_BLOCK);
610 /* Check input arguments. */
611 if ((n_tokens != 2) ||
612 (strcmp(tokens[1], "exact") &&
613 strcmp(tokens[1], "wildcard") &&
614 strcmp(tokens[1], "lpm"))) {
618 *err_msg = "Invalid match field statement.";
622 if (!strcmp(tokens[1], "wildcard"))
623 match_type = RTE_SWX_TABLE_MATCH_WILDCARD;
624 if (!strcmp(tokens[1], "lpm"))
625 match_type = RTE_SWX_TABLE_MATCH_LPM;
626 if (!strcmp(tokens[1], "exact"))
627 match_type = RTE_SWX_TABLE_MATCH_EXACT;
629 name = strdup(tokens[0]);
634 *err_msg = "Memory allocation failed.";
638 new_fields = realloc(s->params.fields,
639 (s->params.n_fields + 1) * sizeof(struct rte_swx_match_field_params));
646 *err_msg = "Memory allocation failed.";
650 s->params.fields = new_fields;
651 s->params.fields[s->params.n_fields].name = name;
652 s->params.fields[s->params.n_fields].match_type = match_type;
653 s->params.n_fields++;
659 table_actions_statement_parse(uint32_t *block_mask,
664 const char **err_msg)
667 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
671 *err_msg = "Invalid actions statement.";
676 *block_mask |= 1 << TABLE_ACTIONS_BLOCK;
682 table_actions_block_parse(struct table_spec *s,
683 uint32_t *block_mask,
688 const char **err_msg)
690 const char **new_action_names;
693 /* Handle end of block. */
694 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
695 *block_mask &= ~(1 << TABLE_ACTIONS_BLOCK);
699 /* Check input arguments. */
704 *err_msg = "Invalid action name statement.";
708 name = strdup(tokens[0]);
713 *err_msg = "Memory allocation failed.";
717 new_action_names = realloc(s->params.action_names,
718 (s->params.n_actions + 1) * sizeof(char *));
719 if (!new_action_names) {
725 *err_msg = "Memory allocation failed.";
729 s->params.action_names = new_action_names;
730 s->params.action_names[s->params.n_actions] = name;
731 s->params.n_actions++;
737 table_statement_parse(struct table_spec *s,
738 uint32_t *block_mask,
743 const char **err_msg)
746 if ((n_tokens != 3) || strcmp(tokens[2], "{")) {
750 *err_msg = "Invalid table statement.";
755 s->name = strdup(tokens[1]);
760 *err_msg = "Memory allocation failed.";
765 *block_mask |= 1 << TABLE_BLOCK;
771 table_block_parse(struct table_spec *s,
772 uint32_t *block_mask,
777 const char **err_msg)
779 if (*block_mask & (1 << TABLE_KEY_BLOCK))
780 return table_key_block_parse(s,
788 if (*block_mask & (1 << TABLE_ACTIONS_BLOCK))
789 return table_actions_block_parse(s,
797 /* Handle end of block. */
798 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
799 *block_mask &= ~(1 << TABLE_BLOCK);
803 if (!strcmp(tokens[0], "key"))
804 return table_key_statement_parse(block_mask,
811 if (!strcmp(tokens[0], "actions"))
812 return table_actions_statement_parse(block_mask,
819 if (!strcmp(tokens[0], "default_action")) {
820 if (((n_tokens != 4) && (n_tokens != 5)) ||
821 strcmp(tokens[2], "args") ||
822 strcmp(tokens[3], "none") ||
823 ((n_tokens == 5) && strcmp(tokens[4], "const"))) {
827 *err_msg = "Invalid default_action statement.";
831 if (s->params.default_action_name) {
835 *err_msg = "Duplicate default_action stmt.";
839 s->params.default_action_name = strdup(tokens[1]);
840 if (!s->params.default_action_name) {
844 *err_msg = "Memory allocation failed.";
849 s->params.default_action_is_const = 1;
854 if (!strcmp(tokens[0], "instanceof")) {
859 *err_msg = "Invalid instanceof statement.";
863 if (s->recommended_table_type_name) {
867 *err_msg = "Duplicate instanceof statement.";
871 s->recommended_table_type_name = strdup(tokens[1]);
872 if (!s->recommended_table_type_name) {
876 *err_msg = "Memory allocation failed.";
883 if (!strcmp(tokens[0], "pragma")) {
888 *err_msg = "Invalid pragma statement.";
896 *err_msg = "Duplicate pragma statement.";
900 s->args = strdup(tokens[1]);
905 *err_msg = "Memory allocation failed.";
912 if (!strcmp(tokens[0], "size")) {
919 *err_msg = "Invalid pragma statement.";
923 s->size = strtoul(p, &p, 0);
928 *err_msg = "Invalid size argument.";
939 *err_msg = "Invalid statement.";
946 * regarray NAME size SIZE initval INITVAL
948 struct regarray_spec {
955 regarray_spec_free(struct regarray_spec *s)
965 regarray_statement_parse(struct regarray_spec *s,
970 const char **err_msg)
975 if ((n_tokens != 6) ||
976 strcmp(tokens[2], "size") ||
977 strcmp(tokens[4], "initval")) {
981 *err_msg = "Invalid regarray statement.";
986 s->name = strdup(tokens[1]);
991 *err_msg = "Memory allocation failed.";
996 s->size = strtoul(p, &p, 0);
997 if (p[0] || !s->size) {
1001 *err_msg = "Invalid size argument.";
1006 s->init_val = strtoull(p, &p, 0);
1009 *err_line = n_lines;
1011 *err_msg = "Invalid initval argument.";
1021 * metarray NAME size SIZE
1023 struct metarray_spec {
1029 metarray_spec_free(struct metarray_spec *s)
1039 metarray_statement_parse(struct metarray_spec *s,
1044 const char **err_msg)
1049 if ((n_tokens != 4) || strcmp(tokens[2], "size")) {
1051 *err_line = n_lines;
1053 *err_msg = "Invalid metarray statement.";
1058 s->name = strdup(tokens[1]);
1061 *err_line = n_lines;
1063 *err_msg = "Memory allocation failed.";
1068 s->size = strtoul(p, &p, 0);
1069 if (p[0] || !s->size) {
1071 *err_line = n_lines;
1073 *err_msg = "Invalid size argument.";
1089 const char **instructions;
1090 uint32_t n_instructions;
1094 apply_spec_free(struct apply_spec *s)
1101 for (i = 0; i < s->n_instructions; i++) {
1102 uintptr_t instr = (uintptr_t)s->instructions[i];
1104 free((void *)instr);
1107 free(s->instructions);
1108 s->instructions = NULL;
1110 s->n_instructions = 0;
1114 apply_statement_parse(uint32_t *block_mask,
1119 const char **err_msg)
1122 if ((n_tokens != 2) || strcmp(tokens[1], "{")) {
1124 *err_line = n_lines;
1126 *err_msg = "Invalid apply statement.";
1131 *block_mask |= 1 << APPLY_BLOCK;
1137 apply_block_parse(struct apply_spec *s,
1138 uint32_t *block_mask,
1143 const char **err_msg)
1145 char buffer[RTE_SWX_INSTRUCTION_SIZE], *instr;
1146 const char **new_instructions;
1149 /* Handle end of block. */
1150 if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
1151 *block_mask &= ~(1 << APPLY_BLOCK);
1157 for (i = 0; i < n_tokens; i++) {
1159 strcat(buffer, " ");
1160 strcat(buffer, tokens[i]);
1163 instr = strdup(buffer);
1166 *err_line = n_lines;
1168 *err_msg = "Memory allocation failed.";
1172 new_instructions = realloc(s->instructions,
1173 (s->n_instructions + 1) * sizeof(char *));
1174 if (!new_instructions) {
1178 *err_line = n_lines;
1180 *err_msg = "Memory allocation failed.";
1184 s->instructions = new_instructions;
1185 s->instructions[s->n_instructions] = instr;
1186 s->n_instructions++;
1195 rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
1198 const char **err_msg)
1200 struct extobj_spec extobj_spec = {0};
1201 struct struct_spec struct_spec = {0};
1202 struct header_spec header_spec = {0};
1203 struct metadata_spec metadata_spec = {0};
1204 struct action_spec action_spec = {0};
1205 struct table_spec table_spec = {0};
1206 struct regarray_spec regarray_spec = {0};
1207 struct metarray_spec metarray_spec = {0};
1208 struct apply_spec apply_spec = {0};
1210 uint32_t block_mask = 0;
1213 /* Check the input arguments. */
1218 *err_msg = "Null pipeline arument.";
1227 *err_msg = "Null specification file argument.";
1232 for (n_lines = 1; ; n_lines++) {
1233 char line[MAX_LINE_LENGTH];
1234 char *tokens[MAX_TOKENS], *ptr = line;
1235 uint32_t n_tokens = 0;
1237 /* Read next line. */
1238 if (!fgets(line, sizeof(line), spec))
1241 /* Parse the line into tokens. */
1246 token = strtok_r(ptr, " \f\n\r\t\v", &ptr);
1250 /* Handle comments. */
1251 if ((token[0] == '#') ||
1252 (token[0] == ';') ||
1253 ((token[0] == '/') && (token[1] == '/'))) {
1257 /* Handle excessively long lines. */
1258 if (n_tokens >= MAX_TOKENS) {
1260 *err_line = n_lines;
1262 *err_msg = "Too many tokens.";
1267 /* Handle excessively long tokens. */
1268 if (strnlen(token, RTE_SWX_NAME_SIZE) >=
1269 RTE_SWX_NAME_SIZE) {
1271 *err_line = n_lines;
1273 *err_msg = "Token too big.";
1279 tokens[n_tokens] = token;
1283 /* Handle empty lines. */
1288 if (block_mask & (1 << STRUCT_BLOCK)) {
1289 status = struct_block_parse(&struct_spec,
1299 if (block_mask & (1 << STRUCT_BLOCK))
1303 status = rte_swx_pipeline_struct_type_register(p,
1306 struct_spec.n_fields);
1309 *err_line = n_lines;
1311 *err_msg = "Struct registration error.";
1315 struct_spec_free(&struct_spec);
1321 if (block_mask & (1 << ACTION_BLOCK)) {
1322 status = action_block_parse(&action_spec,
1332 if (block_mask & (1 << ACTION_BLOCK))
1336 status = rte_swx_pipeline_action_config(p,
1338 action_spec.args_struct_type_name,
1339 action_spec.instructions,
1340 action_spec.n_instructions);
1343 *err_line = n_lines;
1345 *err_msg = "Action config error.";
1349 action_spec_free(&action_spec);
1355 if (block_mask & (1 << TABLE_BLOCK)) {
1356 status = table_block_parse(&table_spec,
1366 if (block_mask & (1 << TABLE_BLOCK))
1370 status = rte_swx_pipeline_table_config(p,
1373 table_spec.recommended_table_type_name,
1378 *err_line = n_lines;
1380 *err_msg = "Table configuration error.";
1384 table_spec_free(&table_spec);
1390 if (block_mask & (1 << APPLY_BLOCK)) {
1391 status = apply_block_parse(&apply_spec,
1401 if (block_mask & (1 << APPLY_BLOCK))
1405 status = rte_swx_pipeline_instructions_config(p,
1406 apply_spec.instructions,
1407 apply_spec.n_instructions);
1410 *err_line = n_lines;
1412 *err_msg = "Pipeline instructions err.";
1416 apply_spec_free(&apply_spec);
1422 if (!strcmp(tokens[0], "extobj")) {
1423 status = extobj_statement_parse(&extobj_spec,
1432 status = rte_swx_pipeline_extern_object_config(p,
1434 extobj_spec.extern_type_name,
1435 extobj_spec.pragma);
1438 *err_line = n_lines;
1440 *err_msg = "Extern object config err.";
1444 extobj_spec_free(&extobj_spec);
1450 if (!strcmp(tokens[0], "struct")) {
1451 status = struct_statement_parse(&struct_spec,
1465 if (!strcmp(tokens[0], "header")) {
1466 status = header_statement_parse(&header_spec,
1475 status = rte_swx_pipeline_packet_header_register(p,
1477 header_spec.struct_type_name);
1480 *err_line = n_lines;
1482 *err_msg = "Header registration error.";
1486 header_spec_free(&header_spec);
1492 if (!strcmp(tokens[0], "metadata")) {
1493 status = metadata_statement_parse(&metadata_spec,
1502 status = rte_swx_pipeline_packet_metadata_register(p,
1503 metadata_spec.struct_type_name);
1506 *err_line = n_lines;
1508 *err_msg = "Meta-data reg err.";
1512 metadata_spec_free(&metadata_spec);
1518 if (!strcmp(tokens[0], "action")) {
1519 status = action_statement_parse(&action_spec,
1533 if (!strcmp(tokens[0], "table")) {
1534 status = table_statement_parse(&table_spec,
1548 if (!strcmp(tokens[0], "regarray")) {
1549 status = regarray_statement_parse(®array_spec,
1558 status = rte_swx_pipeline_regarray_config(p,
1561 regarray_spec.init_val);
1564 *err_line = n_lines;
1566 *err_msg = "Register array configuration error.";
1570 regarray_spec_free(®array_spec);
1576 if (!strcmp(tokens[0], "metarray")) {
1577 status = metarray_statement_parse(&metarray_spec,
1586 status = rte_swx_pipeline_metarray_config(p,
1588 metarray_spec.size);
1591 *err_line = n_lines;
1593 *err_msg = "Meter array configuration error.";
1597 metarray_spec_free(&metarray_spec);
1603 if (!strcmp(tokens[0], "apply")) {
1604 status = apply_statement_parse(&block_mask,
1616 /* Anything else. */
1618 *err_line = n_lines;
1620 *err_msg = "Unknown statement.";
1625 /* Handle unfinished block. */
1628 *err_line = n_lines;
1630 *err_msg = "Missing }.";
1635 /* Pipeline build. */
1636 status = rte_swx_pipeline_build(p);
1639 *err_line = n_lines;
1641 *err_msg = "Pipeline build error.";
1648 extobj_spec_free(&extobj_spec);
1649 struct_spec_free(&struct_spec);
1650 header_spec_free(&header_spec);
1651 metadata_spec_free(&metadata_spec);
1652 action_spec_free(&action_spec);
1653 table_spec_free(&table_spec);
1654 regarray_spec_free(®array_spec);
1655 metarray_spec_free(&metarray_spec);
1656 apply_spec_free(&apply_spec);