X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Fpipeline%2Frte_swx_pipeline_spec.c;h=07a7580ac8398aae74dcebb5d61ecbc01415122a;hb=f3ca33bb20925cca90184bd3f05ebedc78a929b2;hp=c57893f18c45ab7bbf24b8612a85176bf7d7d220;hpb=cef3896928b7de97aa1a74f20fada796996a68d9;p=dpdk.git diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c index c57893f18c..07a7580ac8 100644 --- a/lib/pipeline/rte_swx_pipeline_spec.c +++ b/lib/pipeline/rte_swx_pipeline_spec.c @@ -20,7 +20,10 @@ #define TABLE_ACTIONS_BLOCK 4 #define SELECTOR_BLOCK 5 #define SELECTOR_SELECTOR_BLOCK 6 -#define APPLY_BLOCK 7 +#define LEARNER_BLOCK 7 +#define LEARNER_KEY_BLOCK 8 +#define LEARNER_ACTIONS_BLOCK 9 +#define APPLY_BLOCK 10 /* * extobj. @@ -536,7 +539,7 @@ action_block_parse(struct action_spec *s, * ... * } * actions { - * ACTION_NAME + * ACTION_NAME [ @tableonly | @defaultonly ] * ... * } * default_action ACTION_NAME args none | ARGS_BYTE_ARRAY [ const ] @@ -594,6 +597,12 @@ table_spec_free(struct table_spec *s) 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); @@ -727,8 +736,10 @@ table_actions_block_parse(struct table_spec *s, 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], "}")) { @@ -737,7 +748,9 @@ table_actions_block_parse(struct table_spec *s, } /* 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) @@ -746,18 +759,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; @@ -768,6 +793,13 @@ 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; @@ -1281,6 +1313,427 @@ selector_block_parse(struct selector_spec *s, return -EINVAL; } +/* + * learner. + * + * learner { + * key { + * MATCH_FIELD_NAME + * ... + * } + * actions { + * ACTION_NAME [ @tableonly | @defaultonly] + * ... + * } + * default_action ACTION_NAME args none | ARGS_BYTE_ARRAY [ const ] + * size SIZE + * timeout TIMEOUT_IN_SECONDS + * } + */ +struct learner_spec { + char *name; + struct rte_swx_pipeline_learner_params params; + uint32_t size; + uint32_t timeout; +}; + +static void +learner_spec_free(struct learner_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.field_names[i]; + + free((void *)name); + } + + free(s->params.field_names); + s->params.field_names = 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; + + s->size = 0; + + s->timeout = 0; +} + +static int +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], "{")) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid key statement."; + return -EINVAL; + } + + /* block_mask. */ + *block_mask |= 1 << LEARNER_KEY_BLOCK; + + return 0; +} + +static int +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) +{ + const char **new_field_names = NULL; + char *field_name = NULL; + + /* Handle end of block. */ + if ((n_tokens == 1) && !strcmp(tokens[0], "}")) { + *block_mask &= ~(1 << LEARNER_KEY_BLOCK); + return 0; + } + + /* Check input arguments. */ + if (n_tokens != 1) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid match field statement."; + return -EINVAL; + } + + 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; + if (err_msg) + *err_msg = "Memory allocation failed."; + return -ENOMEM; + } + + 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 +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], "{")) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid actions statement."; + return -EINVAL; + } + + /* block_mask. */ + *block_mask |= 1 << LEARNER_ACTIONS_BLOCK; + + return 0; +} + +static int +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 = 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 << LEARNER_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 +learner_statement_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) +{ + /* Check format. */ + if ((n_tokens != 3) || strcmp(tokens[2], "{")) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid learner 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 << LEARNER_BLOCK; + + return 0; +} + +static int +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 << 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 << LEARNER_BLOCK); + return 0; + } + + if (!strcmp(tokens[0], "key")) + return learner_key_statement_parse(block_mask, + tokens, + n_tokens, + n_lines, + err_line, + err_msg); + + if (!strcmp(tokens[0], "actions")) + 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)) || + 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], "size")) { + char *p = tokens[1]; + + if (n_tokens != 2) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid size 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; + } + + 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 timeout statement."; + return -EINVAL; + } + + s->timeout = strtoul(p, &p, 0); + if (p[0]) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid timeout argument."; + return -EINVAL; + } + + return 0; + } + + /* Anything else. */ + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid statement."; + return -EINVAL; +} + /* * regarray. * @@ -1545,6 +1998,7 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p, 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}; @@ -1557,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; } @@ -1761,6 +2215,40 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p, 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, @@ -1934,6 +2422,21 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p, 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, @@ -2042,6 +2545,7 @@ error: 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);