X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Fpipeline%2Frte_swx_pipeline_spec.c;h=07a7580ac8398aae74dcebb5d61ecbc01415122a;hb=f3ca33bb20925cca90184bd3f05ebedc78a929b2;hp=2e867d7bf216b66d1ac2bd9557161aa2bc44a34c;hpb=99a2dd955fba6e4cc23b77d590a033650ced9c45;p=dpdk.git diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c index 2e867d7bf2..07a7580ac8 100644 --- a/lib/pipeline/rte_swx_pipeline_spec.c +++ b/lib/pipeline/rte_swx_pipeline_spec.c @@ -18,7 +18,12 @@ #define TABLE_BLOCK 2 #define TABLE_KEY_BLOCK 3 #define TABLE_ACTIONS_BLOCK 4 -#define APPLY_BLOCK 5 +#define SELECTOR_BLOCK 5 +#define SELECTOR_SELECTOR_BLOCK 6 +#define LEARNER_BLOCK 7 +#define LEARNER_KEY_BLOCK 8 +#define LEARNER_ACTIONS_BLOCK 9 +#define APPLY_BLOCK 10 /* * extobj. @@ -93,7 +98,7 @@ extobj_statement_parse(struct extobj_spec *s, * struct. * * struct STRUCT_TYPE_NAME { - * bit FIELD_NAME + * bit | varbit FIELD_NAME * ... * } */ @@ -101,6 +106,7 @@ struct struct_spec { char *name; struct rte_swx_field_params *fields; uint32_t n_fields; + int varbit; }; static void @@ -124,6 +130,8 @@ struct_spec_free(struct struct_spec *s) s->fields = NULL; s->n_fields = 0; + + s->varbit = 0; } static int @@ -170,8 +178,9 @@ struct_block_parse(struct struct_spec *s, const char **err_msg) { struct rte_swx_field_params *new_fields; - char *p = tokens[0], *name; + char *p = tokens[0], *name = NULL; uint32_t n_bits; + int varbit = 0, error = 0, error_size_invalid = 0, error_varbit_not_last = 0; /* Handle end of block. */ if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { @@ -180,64 +189,98 @@ struct_block_parse(struct struct_spec *s, } /* Check format. */ - if ((n_tokens != 2) || - (strlen(p) < 6) || - (p[0] != 'b') || - (p[1] != 'i') || - (p[2] != 't') || - (p[3] != '<') || - (p[strlen(p) - 1] != '>')) { - if (err_line) - *err_line = n_lines; - if (err_msg) - *err_msg = "Invalid struct field statement."; - return -EINVAL; + if (n_tokens != 2) { + error = -EINVAL; + goto error; + } + + if (s->varbit) { + error = -EINVAL; + error_varbit_not_last = 1; + goto error; } - /* Remove the "bit<" and ">". */ - p[strlen(p) - 1] = 0; - p += 4; + if (!strncmp(p, "bit<", strlen("bit<"))) { + size_t len = strlen(p); + + if ((len < strlen("bit< >")) || (p[len - 1] != '>')) { + error = -EINVAL; + goto error; + } + + /* Remove the "bit<" and ">". */ + p[strlen(p) - 1] = 0; + p += strlen("bit<"); + } else if (!strncmp(p, "varbit<", strlen("varbit<"))) { + size_t len = strlen(p); + + if ((len < strlen("varbit< >")) || (p[len - 1] != '>')) { + error = -EINVAL; + goto error; + } + + /* Remove the "varbit<" and ">". */ + p[strlen(p) - 1] = 0; + p += strlen("varbit<"); + + /* Set the varbit flag. */ + varbit = 1; + } else { + error = -EINVAL; + goto error; + } n_bits = strtoul(p, &p, 0); if ((p[0]) || !n_bits || (n_bits % 8) || - (n_bits > 64)) { - if (err_line) - *err_line = n_lines; - if (err_msg) - *err_msg = "Invalid struct field size."; - return -EINVAL; + ((n_bits > 64) && !varbit)) { + error = -EINVAL; + error_size_invalid = 1; + goto error; } /* spec. */ name = strdup(tokens[1]); if (!name) { - if (err_line) - *err_line = n_lines; - if (err_msg) - *err_msg = "Memory allocation failed."; - return -ENOMEM; + error = -ENOMEM; + goto error; } - new_fields = realloc(s->fields, - (s->n_fields + 1) * sizeof(struct rte_swx_field_params)); + new_fields = realloc(s->fields, (s->n_fields + 1) * sizeof(struct rte_swx_field_params)); if (!new_fields) { - free(name); - - if (err_line) - *err_line = n_lines; - if (err_msg) - *err_msg = "Memory allocation failed."; - return -ENOMEM; + error = -ENOMEM; + goto error; } s->fields = new_fields; s->fields[s->n_fields].name = name; s->fields[s->n_fields].n_bits = n_bits; s->n_fields++; + s->varbit = varbit; return 0; + +error: + free(name); + + if (err_line) + *err_line = n_lines; + + if (err_msg) { + *err_msg = "Invalid struct field statement."; + + if ((error == -EINVAL) && error_varbit_not_last) + *err_msg = "Varbit field is not the last struct field."; + + if ((error == -EINVAL) && error_size_invalid) + *err_msg = "Invalid struct field size."; + + if (error == -ENOMEM) + *err_msg = "Memory allocation failed."; + } + + return error; } /* @@ -488,33 +531,814 @@ action_block_parse(struct action_spec *s, } /* - * table. + * table. + * + * table { + * key { + * MATCH_FIELD_NAME exact | wildcard | lpm + * ... + * } + * actions { + * ACTION_NAME [ @tableonly | @defaultonly ] + * ... + * } + * default_action ACTION_NAME args none | ARGS_BYTE_ARRAY [ const ] + * instanceof TABLE_TYPE_NAME + * pragma ARGS + * size SIZE + * } + */ +struct table_spec { + char *name; + struct rte_swx_pipeline_table_params params; + char *recommended_table_type_name; + char *args; + uint32_t size; +}; + +static void +table_spec_free(struct table_spec *s) +{ + uintptr_t default_action_name; + uint32_t i; + + if (!s) + return; + + free(s->name); + s->name = NULL; + + for (i = 0; i < s->params.n_fields; i++) { + uintptr_t name = (uintptr_t)s->params.fields[i].name; + + free((void *)name); + } + + free(s->params.fields); + s->params.fields = NULL; + + s->params.n_fields = 0; + + for (i = 0; i < s->params.n_actions; i++) { + uintptr_t name = (uintptr_t)s->params.action_names[i]; + + free((void *)name); + } + + free(s->params.action_names); + s->params.action_names = NULL; + + s->params.n_actions = 0; + + default_action_name = (uintptr_t)s->params.default_action_name; + free((void *)default_action_name); + s->params.default_action_name = NULL; + + free(s->params.default_action_data); + s->params.default_action_data = NULL; + + free(s->params.action_is_for_table_entries); + s->params.action_is_for_table_entries = NULL; + + free(s->params.action_is_for_default_entry); + s->params.action_is_for_default_entry = NULL; + + s->params.default_action_is_const = 0; + + free(s->recommended_table_type_name); + s->recommended_table_type_name = NULL; + + free(s->args); + s->args = NULL; + + s->size = 0; +} + +static int +table_key_statement_parse(uint32_t *block_mask, + char **tokens, + uint32_t n_tokens, + uint32_t n_lines, + uint32_t *err_line, + const char **err_msg) +{ + /* Check format. */ + if ((n_tokens != 2) || strcmp(tokens[1], "{")) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid key statement."; + return -EINVAL; + } + + /* block_mask. */ + *block_mask |= 1 << TABLE_KEY_BLOCK; + + return 0; +} + +static int +table_key_block_parse(struct table_spec *s, + uint32_t *block_mask, + char **tokens, + uint32_t n_tokens, + uint32_t n_lines, + uint32_t *err_line, + const char **err_msg) +{ + struct rte_swx_match_field_params *new_fields; + enum rte_swx_table_match_type match_type = RTE_SWX_TABLE_MATCH_WILDCARD; + char *name; + + /* Handle end of block. */ + if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { + *block_mask &= ~(1 << TABLE_KEY_BLOCK); + return 0; + } + + /* Check input arguments. */ + if ((n_tokens != 2) || + (strcmp(tokens[1], "exact") && + strcmp(tokens[1], "wildcard") && + strcmp(tokens[1], "lpm"))) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid match field statement."; + return -EINVAL; + } + + if (!strcmp(tokens[1], "wildcard")) + match_type = RTE_SWX_TABLE_MATCH_WILDCARD; + if (!strcmp(tokens[1], "lpm")) + match_type = RTE_SWX_TABLE_MATCH_LPM; + if (!strcmp(tokens[1], "exact")) + match_type = RTE_SWX_TABLE_MATCH_EXACT; + + name = strdup(tokens[0]); + if (!name) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Memory allocation failed."; + return -ENOMEM; + } + + new_fields = realloc(s->params.fields, + (s->params.n_fields + 1) * sizeof(struct rte_swx_match_field_params)); + if (!new_fields) { + free(name); + + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Memory allocation failed."; + return -ENOMEM; + } + + s->params.fields = new_fields; + s->params.fields[s->params.n_fields].name = name; + s->params.fields[s->params.n_fields].match_type = match_type; + s->params.n_fields++; + + return 0; +} + +static int +table_actions_statement_parse(uint32_t *block_mask, + char **tokens, + uint32_t n_tokens, + uint32_t n_lines, + uint32_t *err_line, + const char **err_msg) +{ + /* Check format. */ + if ((n_tokens != 2) || strcmp(tokens[1], "{")) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid actions statement."; + return -EINVAL; + } + + /* block_mask. */ + *block_mask |= 1 << TABLE_ACTIONS_BLOCK; + + return 0; +} + +static int +table_actions_block_parse(struct table_spec *s, + uint32_t *block_mask, + char **tokens, + uint32_t n_tokens, + uint32_t n_lines, + uint32_t *err_line, + const char **err_msg) +{ + const char **new_action_names = NULL; + int *new_action_is_for_table_entries = NULL, *new_action_is_for_default_entry = NULL; + char *name = NULL; + int action_is_for_table_entries = 1, action_is_for_default_entry = 1; + + /* Handle end of block. */ + if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { + *block_mask &= ~(1 << TABLE_ACTIONS_BLOCK); + return 0; + } + + /* Check input arguments. */ + if ((n_tokens > 2) || + ((n_tokens == 2) && strcmp(tokens[1], "@tableonly") && + strcmp(tokens[1], "@defaultonly"))) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid action name statement."; + return -EINVAL; + } + + name = strdup(tokens[0]); + + if (n_tokens == 2) { + if (!strcmp(tokens[1], "@tableonly")) + action_is_for_default_entry = 0; + + if (!strcmp(tokens[1], "@defaultonly")) + action_is_for_table_entries = 0; + } + + new_action_names = realloc(s->params.action_names, + (s->params.n_actions + 1) * sizeof(char *)); + new_action_is_for_table_entries = realloc(s->params.action_is_for_table_entries, + (s->params.n_actions + 1) * sizeof(int)); + new_action_is_for_default_entry = realloc(s->params.action_is_for_default_entry, + (s->params.n_actions + 1) * sizeof(int)); + + if (!name || + !new_action_names || + !new_action_is_for_table_entries || + !new_action_is_for_default_entry) { + free(name); + free(new_action_names); + free(new_action_is_for_table_entries); + free(new_action_is_for_default_entry); + + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Memory allocation failed."; + return -ENOMEM; + } + + s->params.action_names = new_action_names; + s->params.action_names[s->params.n_actions] = name; + + s->params.action_is_for_table_entries = new_action_is_for_table_entries; + s->params.action_is_for_table_entries[s->params.n_actions] = action_is_for_table_entries; + + s->params.action_is_for_default_entry = new_action_is_for_default_entry; + s->params.action_is_for_default_entry[s->params.n_actions] = action_is_for_default_entry; + + s->params.n_actions++; + + return 0; +} + +static int +table_statement_parse(struct table_spec *s, + uint32_t *block_mask, + char **tokens, + uint32_t n_tokens, + uint32_t n_lines, + uint32_t *err_line, + const char **err_msg) +{ + /* Check format. */ + if ((n_tokens != 3) || strcmp(tokens[2], "{")) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid table statement."; + return -EINVAL; + } + + /* spec. */ + s->name = strdup(tokens[1]); + if (!s->name) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Memory allocation failed."; + return -ENOMEM; + } + + /* block_mask. */ + *block_mask |= 1 << TABLE_BLOCK; + + return 0; +} + +static int +table_block_parse(struct table_spec *s, + uint32_t *block_mask, + char **tokens, + uint32_t n_tokens, + uint32_t n_lines, + uint32_t *err_line, + const char **err_msg) +{ + if (*block_mask & (1 << TABLE_KEY_BLOCK)) + return table_key_block_parse(s, + block_mask, + tokens, + n_tokens, + n_lines, + err_line, + err_msg); + + if (*block_mask & (1 << TABLE_ACTIONS_BLOCK)) + return table_actions_block_parse(s, + block_mask, + tokens, + n_tokens, + n_lines, + err_line, + err_msg); + + /* Handle end of block. */ + if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { + *block_mask &= ~(1 << TABLE_BLOCK); + return 0; + } + + if (!strcmp(tokens[0], "key")) + return table_key_statement_parse(block_mask, + tokens, + n_tokens, + n_lines, + err_line, + err_msg); + + if (!strcmp(tokens[0], "actions")) + return table_actions_statement_parse(block_mask, + tokens, + n_tokens, + n_lines, + err_line, + err_msg); + + if (!strcmp(tokens[0], "default_action")) { + if (((n_tokens != 4) && (n_tokens != 5)) || + strcmp(tokens[2], "args") || + strcmp(tokens[3], "none") || + ((n_tokens == 5) && strcmp(tokens[4], "const"))) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid default_action statement."; + return -EINVAL; + } + + if (s->params.default_action_name) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Duplicate default_action stmt."; + return -EINVAL; + } + + s->params.default_action_name = strdup(tokens[1]); + if (!s->params.default_action_name) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Memory allocation failed."; + return -ENOMEM; + } + + if (n_tokens == 5) + s->params.default_action_is_const = 1; + + return 0; + } + + if (!strcmp(tokens[0], "instanceof")) { + if (n_tokens != 2) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid instanceof statement."; + return -EINVAL; + } + + if (s->recommended_table_type_name) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Duplicate instanceof statement."; + return -EINVAL; + } + + s->recommended_table_type_name = strdup(tokens[1]); + if (!s->recommended_table_type_name) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Memory allocation failed."; + return -ENOMEM; + } + + return 0; + } + + if (!strcmp(tokens[0], "pragma")) { + if (n_tokens != 2) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid pragma statement."; + return -EINVAL; + } + + if (s->args) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Duplicate pragma statement."; + return -EINVAL; + } + + s->args = strdup(tokens[1]); + if (!s->args) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Memory allocation failed."; + return -ENOMEM; + } + + return 0; + } + + if (!strcmp(tokens[0], "size")) { + char *p = tokens[1]; + + if (n_tokens != 2) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid pragma statement."; + return -EINVAL; + } + + s->size = strtoul(p, &p, 0); + if (p[0]) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid size argument."; + return -EINVAL; + } + + return 0; + } + + /* Anything else. */ + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid statement."; + return -EINVAL; +} + +/* + * selector. + * + * selector SELECTOR_NAME { + * group_id FIELD_NAME + * selector { + * FIELD_NAME + * ... + * } + * member_id FIELD_NAME + * n_groups N_GROUPS + * n_members_per_group N_MEMBERS_PER_GROUP + * } + */ +struct selector_spec { + char *name; + struct rte_swx_pipeline_selector_params params; +}; + +static void +selector_spec_free(struct selector_spec *s) +{ + uintptr_t field_name; + uint32_t i; + + if (!s) + return; + + /* name. */ + free(s->name); + s->name = NULL; + + /* params->group_id_field_name. */ + field_name = (uintptr_t)s->params.group_id_field_name; + free((void *)field_name); + s->params.group_id_field_name = NULL; + + /* params->selector_field_names. */ + for (i = 0; i < s->params.n_selector_fields; i++) { + field_name = (uintptr_t)s->params.selector_field_names[i]; + + free((void *)field_name); + } + + free(s->params.selector_field_names); + s->params.selector_field_names = NULL; + + s->params.n_selector_fields = 0; + + /* params->member_id_field_name. */ + field_name = (uintptr_t)s->params.member_id_field_name; + free((void *)field_name); + s->params.member_id_field_name = NULL; + + /* params->n_groups_max. */ + s->params.n_groups_max = 0; + + /* params->n_members_per_group_max. */ + s->params.n_members_per_group_max = 0; +} + +static int +selector_statement_parse(struct selector_spec *s, + uint32_t *block_mask, + char **tokens, + uint32_t n_tokens, + uint32_t n_lines, + uint32_t *err_line, + const char **err_msg) +{ + /* Check format. */ + if ((n_tokens != 3) || strcmp(tokens[2], "{")) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid selector statement."; + return -EINVAL; + } + + /* spec. */ + s->name = strdup(tokens[1]); + if (!s->name) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Memory allocation failed."; + return -ENOMEM; + } + + /* block_mask. */ + *block_mask |= 1 << SELECTOR_BLOCK; + + return 0; +} + +static int +selector_selector_statement_parse(uint32_t *block_mask, + char **tokens, + uint32_t n_tokens, + uint32_t n_lines, + uint32_t *err_line, + const char **err_msg) +{ + /* Check format. */ + if ((n_tokens != 2) || strcmp(tokens[1], "{")) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid selector statement."; + return -EINVAL; + } + + /* block_mask. */ + *block_mask |= 1 << SELECTOR_SELECTOR_BLOCK; + + return 0; +} + +static int +selector_selector_block_parse(struct selector_spec *s, + uint32_t *block_mask, + char **tokens, + uint32_t n_tokens, + uint32_t n_lines, + uint32_t *err_line, + const char **err_msg) +{ + const char **new_fields; + char *name; + + /* Handle end of block. */ + if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { + *block_mask &= ~(1 << SELECTOR_SELECTOR_BLOCK); + return 0; + } + + /* Check input arguments. */ + if (n_tokens != 1) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid selector field statement."; + return -EINVAL; + } + + name = strdup(tokens[0]); + if (!name) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Memory allocation failed."; + return -ENOMEM; + } + + new_fields = realloc(s->params.selector_field_names, + (s->params.n_selector_fields + 1) * sizeof(char *)); + if (!new_fields) { + free(name); + + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Memory allocation failed."; + return -ENOMEM; + } + + s->params.selector_field_names = new_fields; + s->params.selector_field_names[s->params.n_selector_fields] = name; + s->params.n_selector_fields++; + + return 0; +} + +static int +selector_block_parse(struct selector_spec *s, + uint32_t *block_mask, + char **tokens, + uint32_t n_tokens, + uint32_t n_lines, + uint32_t *err_line, + const char **err_msg) +{ + if (*block_mask & (1 << SELECTOR_SELECTOR_BLOCK)) + return selector_selector_block_parse(s, + block_mask, + tokens, + n_tokens, + n_lines, + err_line, + err_msg); + + /* Handle end of block. */ + if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { + *block_mask &= ~(1 << SELECTOR_BLOCK); + return 0; + } + + if (!strcmp(tokens[0], "group_id")) { + if (n_tokens != 2) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid group_id statement."; + return -EINVAL; + } + + s->params.group_id_field_name = strdup(tokens[1]); + if (!s->params.group_id_field_name) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Memory allocation failed."; + return -ENOMEM; + } + + return 0; + } + + if (!strcmp(tokens[0], "selector")) + return selector_selector_statement_parse(block_mask, + tokens, + n_tokens, + n_lines, + err_line, + err_msg); + + if (!strcmp(tokens[0], "member_id")) { + if (n_tokens != 2) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid member_id statement."; + return -EINVAL; + } + + s->params.member_id_field_name = strdup(tokens[1]); + if (!s->params.member_id_field_name) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Memory allocation failed."; + return -ENOMEM; + } + + return 0; + } + + if (!strcmp(tokens[0], "n_groups_max")) { + char *p = tokens[1]; + + if (n_tokens != 2) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid n_groups statement."; + return -EINVAL; + } + + s->params.n_groups_max = strtoul(p, &p, 0); + if (p[0]) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid n_groups argument."; + return -EINVAL; + } + + return 0; + } + + if (!strcmp(tokens[0], "n_members_per_group_max")) { + char *p = tokens[1]; + + if (n_tokens != 2) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid n_members_per_group statement."; + return -EINVAL; + } + + s->params.n_members_per_group_max = strtoul(p, &p, 0); + if (p[0]) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid n_members_per_group argument."; + return -EINVAL; + } + + return 0; + } + + /* Anything else. */ + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid statement."; + return -EINVAL; +} + +/* + * learner. * - * table { + * learner { * key { - * MATCH_FIELD_NAME exact | wildcard | lpm + * MATCH_FIELD_NAME * ... * } * actions { - * ACTION_NAME + * ACTION_NAME [ @tableonly | @defaultonly] * ... * } * default_action ACTION_NAME args none | ARGS_BYTE_ARRAY [ const ] - * instanceof TABLE_TYPE_NAME - * pragma ARGS * size SIZE + * timeout TIMEOUT_IN_SECONDS * } */ -struct table_spec { +struct learner_spec { char *name; - struct rte_swx_pipeline_table_params params; - char *recommended_table_type_name; - char *args; + struct rte_swx_pipeline_learner_params params; uint32_t size; + uint32_t timeout; }; static void -table_spec_free(struct table_spec *s) +learner_spec_free(struct learner_spec *s) { uintptr_t default_action_name; uint32_t i; @@ -526,13 +1350,13 @@ table_spec_free(struct table_spec *s) s->name = NULL; for (i = 0; i < s->params.n_fields; i++) { - uintptr_t name = (uintptr_t)s->params.fields[i].name; + uintptr_t name = (uintptr_t)s->params.field_names[i]; free((void *)name); } - free(s->params.fields); - s->params.fields = NULL; + free(s->params.field_names); + s->params.field_names = NULL; s->params.n_fields = 0; @@ -554,24 +1378,26 @@ table_spec_free(struct table_spec *s) free(s->params.default_action_data); s->params.default_action_data = NULL; - s->params.default_action_is_const = 0; + free(s->params.action_is_for_table_entries); + s->params.action_is_for_table_entries = NULL; - free(s->recommended_table_type_name); - s->recommended_table_type_name = NULL; + free(s->params.action_is_for_default_entry); + s->params.action_is_for_default_entry = NULL; - free(s->args); - s->args = NULL; + s->params.default_action_is_const = 0; s->size = 0; + + s->timeout = 0; } static int -table_key_statement_parse(uint32_t *block_mask, - char **tokens, - uint32_t n_tokens, - uint32_t n_lines, - uint32_t *err_line, - const char **err_msg) +learner_key_statement_parse(uint32_t *block_mask, + char **tokens, + uint32_t n_tokens, + uint32_t n_lines, + uint32_t *err_line, + const char **err_msg) { /* Check format. */ if ((n_tokens != 2) || strcmp(tokens[1], "{")) { @@ -583,35 +1409,31 @@ table_key_statement_parse(uint32_t *block_mask, } /* block_mask. */ - *block_mask |= 1 << TABLE_KEY_BLOCK; + *block_mask |= 1 << LEARNER_KEY_BLOCK; return 0; } static int -table_key_block_parse(struct table_spec *s, - uint32_t *block_mask, - char **tokens, - uint32_t n_tokens, - uint32_t n_lines, - uint32_t *err_line, - const char **err_msg) +learner_key_block_parse(struct learner_spec *s, + uint32_t *block_mask, + char **tokens, + uint32_t n_tokens, + uint32_t n_lines, + uint32_t *err_line, + const char **err_msg) { - struct rte_swx_match_field_params *new_fields; - enum rte_swx_table_match_type match_type = RTE_SWX_TABLE_MATCH_WILDCARD; - char *name; + const char **new_field_names = NULL; + char *field_name = NULL; /* Handle end of block. */ if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { - *block_mask &= ~(1 << TABLE_KEY_BLOCK); + *block_mask &= ~(1 << LEARNER_KEY_BLOCK); return 0; } /* Check input arguments. */ - if ((n_tokens != 2) || - (strcmp(tokens[1], "exact") && - strcmp(tokens[1], "wildcard") && - strcmp(tokens[1], "lpm"))) { + if (n_tokens != 1) { if (err_line) *err_line = n_lines; if (err_msg) @@ -619,26 +1441,11 @@ table_key_block_parse(struct table_spec *s, return -EINVAL; } - if (!strcmp(tokens[1], "wildcard")) - match_type = RTE_SWX_TABLE_MATCH_WILDCARD; - if (!strcmp(tokens[1], "lpm")) - match_type = RTE_SWX_TABLE_MATCH_LPM; - if (!strcmp(tokens[1], "exact")) - match_type = RTE_SWX_TABLE_MATCH_EXACT; - - name = strdup(tokens[0]); - if (!name) { - if (err_line) - *err_line = n_lines; - if (err_msg) - *err_msg = "Memory allocation failed."; - return -ENOMEM; - } - - new_fields = realloc(s->params.fields, - (s->params.n_fields + 1) * sizeof(struct rte_swx_match_field_params)); - if (!new_fields) { - free(name); + field_name = strdup(tokens[0]); + new_field_names = realloc(s->params.field_names, (s->params.n_fields + 1) * sizeof(char *)); + if (!field_name || !new_field_names) { + free(field_name); + free(new_field_names); if (err_line) *err_line = n_lines; @@ -647,21 +1454,20 @@ table_key_block_parse(struct table_spec *s, return -ENOMEM; } - s->params.fields = new_fields; - s->params.fields[s->params.n_fields].name = name; - s->params.fields[s->params.n_fields].match_type = match_type; + s->params.field_names = new_field_names; + s->params.field_names[s->params.n_fields] = field_name; s->params.n_fields++; return 0; } static int -table_actions_statement_parse(uint32_t *block_mask, - char **tokens, - uint32_t n_tokens, - uint32_t n_lines, - uint32_t *err_line, - const char **err_msg) +learner_actions_statement_parse(uint32_t *block_mask, + char **tokens, + uint32_t n_tokens, + uint32_t n_lines, + uint32_t *err_line, + const char **err_msg) { /* Check format. */ if ((n_tokens != 2) || strcmp(tokens[1], "{")) { @@ -673,31 +1479,35 @@ table_actions_statement_parse(uint32_t *block_mask, } /* block_mask. */ - *block_mask |= 1 << TABLE_ACTIONS_BLOCK; + *block_mask |= 1 << LEARNER_ACTIONS_BLOCK; return 0; } static int -table_actions_block_parse(struct table_spec *s, - uint32_t *block_mask, - char **tokens, - uint32_t n_tokens, - uint32_t n_lines, - uint32_t *err_line, - const char **err_msg) +learner_actions_block_parse(struct learner_spec *s, + uint32_t *block_mask, + char **tokens, + uint32_t n_tokens, + uint32_t n_lines, + uint32_t *err_line, + const char **err_msg) { - const char **new_action_names; - char *name; + const char **new_action_names = NULL; + int *new_action_is_for_table_entries = NULL, *new_action_is_for_default_entry = NULL; + char *name = NULL; + int action_is_for_table_entries = 1, action_is_for_default_entry = 1; /* Handle end of block. */ if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { - *block_mask &= ~(1 << TABLE_ACTIONS_BLOCK); + *block_mask &= ~(1 << LEARNER_ACTIONS_BLOCK); return 0; } /* Check input arguments. */ - if (n_tokens != 1) { + if ((n_tokens > 2) || + ((n_tokens == 2) && strcmp(tokens[1], "@tableonly") && + strcmp(tokens[1], "@defaultonly"))) { if (err_line) *err_line = n_lines; if (err_msg) @@ -706,18 +1516,30 @@ table_actions_block_parse(struct table_spec *s, } name = strdup(tokens[0]); - if (!name) { - if (err_line) - *err_line = n_lines; - if (err_msg) - *err_msg = "Memory allocation failed."; - return -ENOMEM; + + if (n_tokens == 2) { + if (!strcmp(tokens[1], "@tableonly")) + action_is_for_default_entry = 0; + + if (!strcmp(tokens[1], "@defaultonly")) + action_is_for_table_entries = 0; } new_action_names = realloc(s->params.action_names, (s->params.n_actions + 1) * sizeof(char *)); - if (!new_action_names) { + new_action_is_for_table_entries = realloc(s->params.action_is_for_table_entries, + (s->params.n_actions + 1) * sizeof(int)); + new_action_is_for_default_entry = realloc(s->params.action_is_for_default_entry, + (s->params.n_actions + 1) * sizeof(int)); + + if (!name || + !new_action_names || + !new_action_is_for_table_entries || + !new_action_is_for_default_entry) { free(name); + free(new_action_names); + free(new_action_is_for_table_entries); + free(new_action_is_for_default_entry); if (err_line) *err_line = n_lines; @@ -728,13 +1550,20 @@ table_actions_block_parse(struct table_spec *s, s->params.action_names = new_action_names; s->params.action_names[s->params.n_actions] = name; + + s->params.action_is_for_table_entries = new_action_is_for_table_entries; + s->params.action_is_for_table_entries[s->params.n_actions] = action_is_for_table_entries; + + s->params.action_is_for_default_entry = new_action_is_for_default_entry; + s->params.action_is_for_default_entry[s->params.n_actions] = action_is_for_default_entry; + s->params.n_actions++; return 0; } static int -table_statement_parse(struct table_spec *s, +learner_statement_parse(struct learner_spec *s, uint32_t *block_mask, char **tokens, uint32_t n_tokens, @@ -747,7 +1576,7 @@ table_statement_parse(struct table_spec *s, if (err_line) *err_line = n_lines; if (err_msg) - *err_msg = "Invalid table statement."; + *err_msg = "Invalid learner statement."; return -EINVAL; } @@ -762,59 +1591,59 @@ table_statement_parse(struct table_spec *s, } /* block_mask. */ - *block_mask |= 1 << TABLE_BLOCK; + *block_mask |= 1 << LEARNER_BLOCK; return 0; } static int -table_block_parse(struct table_spec *s, - uint32_t *block_mask, - char **tokens, - uint32_t n_tokens, - uint32_t n_lines, - uint32_t *err_line, - const char **err_msg) +learner_block_parse(struct learner_spec *s, + uint32_t *block_mask, + char **tokens, + uint32_t n_tokens, + uint32_t n_lines, + uint32_t *err_line, + const char **err_msg) { - if (*block_mask & (1 << TABLE_KEY_BLOCK)) - return table_key_block_parse(s, - block_mask, - tokens, - n_tokens, - n_lines, - err_line, - err_msg); - - if (*block_mask & (1 << TABLE_ACTIONS_BLOCK)) - return table_actions_block_parse(s, - block_mask, - tokens, - n_tokens, - n_lines, - err_line, - err_msg); + if (*block_mask & (1 << LEARNER_KEY_BLOCK)) + return learner_key_block_parse(s, + block_mask, + tokens, + n_tokens, + n_lines, + err_line, + err_msg); + + if (*block_mask & (1 << LEARNER_ACTIONS_BLOCK)) + return learner_actions_block_parse(s, + block_mask, + tokens, + n_tokens, + n_lines, + err_line, + err_msg); /* Handle end of block. */ if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { - *block_mask &= ~(1 << TABLE_BLOCK); + *block_mask &= ~(1 << LEARNER_BLOCK); return 0; } if (!strcmp(tokens[0], "key")) - return table_key_statement_parse(block_mask, - tokens, - n_tokens, - n_lines, - err_line, - err_msg); + return learner_key_statement_parse(block_mask, + tokens, + n_tokens, + n_lines, + err_line, + err_msg); if (!strcmp(tokens[0], "actions")) - return table_actions_statement_parse(block_mask, - tokens, - n_tokens, - n_lines, - err_line, - err_msg); + return learner_actions_statement_parse(block_mask, + tokens, + n_tokens, + n_lines, + err_line, + err_msg); if (!strcmp(tokens[0], "default_action")) { if (((n_tokens != 4) && (n_tokens != 5)) || @@ -851,81 +1680,46 @@ table_block_parse(struct table_spec *s, return 0; } - if (!strcmp(tokens[0], "instanceof")) { - if (n_tokens != 2) { - if (err_line) - *err_line = n_lines; - if (err_msg) - *err_msg = "Invalid instanceof statement."; - return -EINVAL; - } - - if (s->recommended_table_type_name) { - if (err_line) - *err_line = n_lines; - if (err_msg) - *err_msg = "Duplicate instanceof statement."; - return -EINVAL; - } - - s->recommended_table_type_name = strdup(tokens[1]); - if (!s->recommended_table_type_name) { - if (err_line) - *err_line = n_lines; - if (err_msg) - *err_msg = "Memory allocation failed."; - return -ENOMEM; - } - - return 0; - } + if (!strcmp(tokens[0], "size")) { + char *p = tokens[1]; - if (!strcmp(tokens[0], "pragma")) { if (n_tokens != 2) { if (err_line) *err_line = n_lines; if (err_msg) - *err_msg = "Invalid pragma statement."; + *err_msg = "Invalid size statement."; return -EINVAL; } - if (s->args) { + s->size = strtoul(p, &p, 0); + if (p[0]) { if (err_line) *err_line = n_lines; if (err_msg) - *err_msg = "Duplicate pragma statement."; + *err_msg = "Invalid size argument."; return -EINVAL; } - s->args = strdup(tokens[1]); - if (!s->args) { - if (err_line) - *err_line = n_lines; - if (err_msg) - *err_msg = "Memory allocation failed."; - return -ENOMEM; - } - return 0; } - if (!strcmp(tokens[0], "size")) { + if (!strcmp(tokens[0], "timeout")) { char *p = tokens[1]; if (n_tokens != 2) { if (err_line) *err_line = n_lines; if (err_msg) - *err_msg = "Invalid pragma statement."; + *err_msg = "Invalid timeout statement."; return -EINVAL; } - s->size = strtoul(p, &p, 0); + s->timeout = strtoul(p, &p, 0); if (p[0]) { if (err_line) *err_line = n_lines; if (err_msg) - *err_msg = "Invalid size argument."; + *err_msg = "Invalid timeout argument."; return -EINVAL; } @@ -1203,6 +1997,8 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p, struct metadata_spec metadata_spec = {0}; struct action_spec action_spec = {0}; struct table_spec table_spec = {0}; + struct selector_spec selector_spec = {0}; + struct learner_spec learner_spec = {0}; struct regarray_spec regarray_spec = {0}; struct metarray_spec metarray_spec = {0}; struct apply_spec apply_spec = {0}; @@ -1215,7 +2011,7 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p, if (err_line) *err_line = 0; if (err_msg) - *err_msg = "Null pipeline arument."; + *err_msg = "Null pipeline argument."; status = -EINVAL; goto error; } @@ -1303,7 +2099,8 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p, status = rte_swx_pipeline_struct_type_register(p, struct_spec.name, struct_spec.fields, - struct_spec.n_fields); + struct_spec.n_fields, + struct_spec.varbit); if (status) { if (err_line) *err_line = n_lines; @@ -1386,6 +2183,72 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p, continue; } + /* selector block. */ + if (block_mask & (1 << SELECTOR_BLOCK)) { + status = selector_block_parse(&selector_spec, + &block_mask, + tokens, + n_tokens, + n_lines, + err_line, + err_msg); + if (status) + goto error; + + if (block_mask & (1 << SELECTOR_BLOCK)) + continue; + + /* End of block. */ + status = rte_swx_pipeline_selector_config(p, + selector_spec.name, + &selector_spec.params); + if (status) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Selector configuration error."; + goto error; + } + + selector_spec_free(&selector_spec); + + continue; + } + + /* learner block. */ + if (block_mask & (1 << LEARNER_BLOCK)) { + status = learner_block_parse(&learner_spec, + &block_mask, + tokens, + n_tokens, + n_lines, + err_line, + err_msg); + if (status) + goto error; + + if (block_mask & (1 << LEARNER_BLOCK)) + continue; + + /* End of block. */ + status = rte_swx_pipeline_learner_config(p, + learner_spec.name, + &learner_spec.params, + learner_spec.size, + learner_spec.timeout); + if (status) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Learner table configuration error."; + goto error; + } + + learner_spec_free(&learner_spec); + + continue; + } + /* apply block. */ if (block_mask & (1 << APPLY_BLOCK)) { status = apply_block_parse(&apply_spec, @@ -1544,6 +2407,36 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p, continue; } + /* selector. */ + if (!strcmp(tokens[0], "selector")) { + status = selector_statement_parse(&selector_spec, + &block_mask, + tokens, + n_tokens, + n_lines, + err_line, + err_msg); + if (status) + goto error; + + continue; + } + + /* learner. */ + if (!strcmp(tokens[0], "learner")) { + status = learner_statement_parse(&learner_spec, + &block_mask, + tokens, + n_tokens, + n_lines, + err_line, + err_msg); + if (status) + goto error; + + continue; + } + /* regarray. */ if (!strcmp(tokens[0], "regarray")) { status = regarray_statement_parse(®array_spec, @@ -1651,6 +2544,8 @@ error: metadata_spec_free(&metadata_spec); action_spec_free(&action_spec); table_spec_free(&table_spec); + selector_spec_free(&selector_spec); + learner_spec_free(&learner_spec); regarray_spec_free(®array_spec); metarray_spec_free(&metarray_spec); apply_spec_free(&apply_spec);