From 393b96e2aa2a578bc38a35f436a31cf42b04cc37 Mon Sep 17 00:00:00 2001 From: Cristian Dumitrescu Date: Thu, 1 Oct 2020 11:19:57 +0100 Subject: [PATCH] pipeline: add SWX pipeline query API Query API to be used by the control plane to detect the configuration and state of the SWX pipeline and its internal objects. Signed-off-by: Cristian Dumitrescu --- lib/librte_pipeline/rte_pipeline_version.map | 10 + lib/librte_pipeline/rte_swx_ctl.h | 313 +++++++++++++++++++ lib/librte_pipeline/rte_swx_pipeline.c | 219 +++++++++++++ 3 files changed, 542 insertions(+) diff --git a/lib/librte_pipeline/rte_pipeline_version.map b/lib/librte_pipeline/rte_pipeline_version.map index 861682e956..b1e0ab65f6 100644 --- a/lib/librte_pipeline/rte_pipeline_version.map +++ b/lib/librte_pipeline/rte_pipeline_version.map @@ -60,6 +60,16 @@ EXPERIMENTAL { rte_table_action_crypto_sym_session_get; # added in 20.11 + rte_swx_ctl_action_arg_info_get; + rte_swx_ctl_action_info_get; + rte_swx_ctl_pipeline_info_get; + rte_swx_ctl_pipeline_numa_node_get; + rte_swx_ctl_pipeline_port_in_stats_read; + rte_swx_ctl_pipeline_port_out_stats_read; + rte_swx_ctl_table_action_info_get; + rte_swx_ctl_table_info_get; + rte_swx_ctl_table_match_field_info_get; + rte_swx_ctl_table_ops_get; rte_swx_pipeline_action_config; rte_swx_pipeline_build; rte_swx_pipeline_config; diff --git a/lib/librte_pipeline/rte_swx_ctl.h b/lib/librte_pipeline/rte_swx_ctl.h index c824ab56fe..54b895f0ad 100644 --- a/lib/librte_pipeline/rte_swx_ctl.h +++ b/lib/librte_pipeline/rte_swx_ctl.h @@ -18,8 +18,321 @@ extern "C" { #include +#include "rte_swx_port.h" #include "rte_swx_table.h" +struct rte_swx_pipeline; + +/** Name size. */ +#ifndef RTE_SWX_CTL_NAME_SIZE +#define RTE_SWX_CTL_NAME_SIZE 64 +#endif + +/* + * Pipeline Query API. + */ + +/** Pipeline info. */ +struct rte_swx_ctl_pipeline_info { + /** Number of input ports. */ + uint32_t n_ports_in; + + /** Number of input ports. */ + uint32_t n_ports_out; + + /** Number of actions. */ + uint32_t n_actions; + + /** Number of tables. */ + uint32_t n_tables; +}; + +/** + * Pipeline info get + * + * @param[in] p + * Pipeline handle. + * @param[out] pipeline + * Pipeline info. + * @return + * 0 on success or the following error codes otherwise: + * -EINVAL: Invalid argument. + */ +__rte_experimental +int +rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p, + struct rte_swx_ctl_pipeline_info *pipeline); + +/** + * Pipeline NUMA node get + * + * @param[in] p + * Pipeline handle. + * @param[out] numa_node + * Pipeline NUMA node. + * @return + * 0 on success or the following error codes otherwise: + * -EINVAL: Invalid argument. + */ +__rte_experimental +int +rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, + int *numa_node); + +/* + * Ports Query API. + */ + +/** + * Input port statistics counters read + * + * @param[in] p + * Pipeline handle. + * @param[in] port_id + * Port ID (0 .. *n_ports_in* - 1). + * @param[out] stats + * Input port stats. + * @return + * 0 on success or the following error codes otherwise: + * -EINVAL: Invalid argument. + */ +__rte_experimental +int +rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p, + uint32_t port_id, + struct rte_swx_port_in_stats *stats); + +/** + * Output port statistics counters read + * + * @param[in] p + * Pipeline handle. + * @param[in] port_id + * Port ID (0 .. *n_ports_out* - 1). + * @param[out] stats + * Output port stats. + * @return + * 0 on success or the following error codes otherwise: + * -EINVAL: Invalid argument. + */ +__rte_experimental +int +rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p, + uint32_t port_id, + struct rte_swx_port_out_stats *stats); + +/* + * Action Query API. + */ + +/** Action info. */ +struct rte_swx_ctl_action_info { + /** Action name. */ + char name[RTE_SWX_CTL_NAME_SIZE]; + + /** Number of action arguments. */ + uint32_t n_args; +}; + +/** + * Action info get + * + * @param[in] p + * Pipeline handle. + * @param[in] action_id + * Action ID (0 .. *n_actions* - 1). + * @param[out] action + * Action info. + * @return + * 0 on success or the following error codes otherwise: + * -EINVAL: Invalid argument. + */ +__rte_experimental +int +rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p, + uint32_t action_id, + struct rte_swx_ctl_action_info *action); + +/** Action argument info. */ +struct rte_swx_ctl_action_arg_info { + /** Action argument name. */ + char name[RTE_SWX_CTL_NAME_SIZE]; + + /** Action argument size (in bits). */ + uint32_t n_bits; +}; + +/** + * Action argument info get + * + * @param[in] p + * Pipeline handle. + * @param[in] action_id + * Action ID (0 .. *n_actions* - 1). + * @param[in] action_arg_id + * Action ID (0 .. *n_args* - 1). + * @param[out] action_arg + * Action argument info. + * @return + * 0 on success or the following error codes otherwise: + * -EINVAL: Invalid argument. + */ +__rte_experimental +int +rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p, + uint32_t action_id, + uint32_t action_arg_id, + struct rte_swx_ctl_action_arg_info *action_arg); + +/* + * Table Query API. + */ + +/** Table info. */ +struct rte_swx_ctl_table_info { + /** Table name. */ + char name[RTE_SWX_CTL_NAME_SIZE]; + + /** Table creation arguments. */ + char args[RTE_SWX_CTL_NAME_SIZE]; + + /** Number of match fields. */ + uint32_t n_match_fields; + + /** Number of actions. */ + uint32_t n_actions; + + /** Non-zero (true) when the default action is constant, therefore it + * cannot be changed; zero (false) when the default action not constant, + * therefore it can be changed. + */ + int default_action_is_const; + + /** Table size parameter. */ + uint32_t size; +}; + +/** + * Table info get + * + * @param[in] p + * Pipeline handle. + * @param[in] table_id + * Table ID (0 .. *n_tables* - 1). + * @param[out] table + * Table info. + * @return + * 0 on success or the following error codes otherwise: + * -EINVAL: Invalid argument. + */ +__rte_experimental +int +rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p, + uint32_t table_id, + struct rte_swx_ctl_table_info *table); + +/** Table match field info. + * + * If (n_bits, offset) are known for all the match fields of the table, then the + * table (key_offset, key_size, key_mask0) can be computed. + */ +struct rte_swx_ctl_table_match_field_info { + /** Match type of the current match field. */ + enum rte_swx_table_match_type match_type; + + /** Non-zero (true) when the current match field is part of a registered + * header, zero (false) when it is part of the registered meta-data. + */ + int is_header; + + /** Match field size (in bits). */ + uint32_t n_bits; + + /** Match field offset within its parent struct (one of the headers or + * the meta-data). + */ + uint32_t offset; +}; + +/** + * Table match field info get + * + * @param[in] p + * Pipeline handle. + * @param[in] table_id + * Table ID (0 .. *n_tables*). + * @param[in] match_field_id + * Match field ID (0 .. *n_match_fields* - 1). + * @param[out] match_field + * Table match field info. + * @return + * 0 on success or the following error codes otherwise: + * -EINVAL: Invalid argument. + */ +__rte_experimental +int +rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p, + uint32_t table_id, + uint32_t match_field_id, + struct rte_swx_ctl_table_match_field_info *match_field); + +/** Table action info. */ +struct rte_swx_ctl_table_action_info { + /** Action ID. */ + uint32_t action_id; +}; + +/** + * Table action info get + * + * @param[in] p + * Pipeline handle. + * @param[in] table_id + * Table ID (0 .. *n_tables*). + * @param[in] table_action_id + * Action index within the set of table actions (0 .. table n_actions - 1). + * Not to be confused with the action ID, which works at the pipeline level + * (0 .. pipeline n_actions - 1), which is precisely what this function + * returns as part of *table_action*. + * @param[out] table_action + * Table action info. + * @return + * 0 on success or the following error codes otherwise: + * -EINVAL: Invalid argument. + */ +__rte_experimental +int +rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p, + uint32_t table_id, + uint32_t table_action_id, + struct rte_swx_ctl_table_action_info *table_action); + +/** + * Table operations get + * + * @param[in] p + * Pipeline handle. + * @param[in] table_id + * Table ID (0 .. *n_tables*). + * @param[out] table_ops + * Table operations. Only valid when function returns success and *is_stub* is + * zero (false). + * @param[out] is_stub + * A stub table is a table with no match fields. No "regular" table entries + * (i.e. entries other than the default entry) can be added to such a table, + * therefore the lookup operation always results in lookup miss. Non-zero + * (true) when the current table is a stub table, zero (false) otherwise. + * @return + * 0 on success or the following error codes otherwise: + * -EINVAL: Invalid argument. + */ +__rte_experimental +int +rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p, + uint32_t table_id, + struct rte_swx_table_ops *table_ops, + int *is_stub); + /* * Table Update API. */ diff --git a/lib/librte_pipeline/rte_swx_pipeline.c b/lib/librte_pipeline/rte_swx_pipeline.c index 77eae19278..da69bab493 100644 --- a/lib/librte_pipeline/rte_swx_pipeline.c +++ b/lib/librte_pipeline/rte_swx_pipeline.c @@ -6152,6 +6152,18 @@ action_find(struct rte_swx_pipeline *p, const char *name) return NULL; } +static struct action * +action_find_by_id(struct rte_swx_pipeline *p, uint32_t id) +{ + struct action *action = NULL; + + TAILQ_FOREACH(action, &p->actions, node) + if (action->id == id) + return action; + + return NULL; +} + static struct field * action_field_find(struct action *a, const char *name) { @@ -6942,6 +6954,177 @@ rte_swx_pipeline_run(struct rte_swx_pipeline *p, uint32_t n_instructions) /* * Control. */ +int +rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p, + struct rte_swx_ctl_pipeline_info *pipeline) +{ + struct action *action; + struct table *table; + uint32_t n_actions = 0, n_tables = 0; + + if (!p || !pipeline) + return -EINVAL; + + TAILQ_FOREACH(action, &p->actions, node) + n_actions++; + + TAILQ_FOREACH(table, &p->tables, node) + n_tables++; + + pipeline->n_ports_in = p->n_ports_in; + pipeline->n_ports_out = p->n_ports_out; + pipeline->n_actions = n_actions; + pipeline->n_tables = n_tables; + + return 0; +} + +int +rte_swx_ctl_pipeline_numa_node_get(struct rte_swx_pipeline *p, int *numa_node) +{ + if (!p || !numa_node) + return -EINVAL; + + *numa_node = p->numa_node; + return 0; +} + +int +rte_swx_ctl_action_info_get(struct rte_swx_pipeline *p, + uint32_t action_id, + struct rte_swx_ctl_action_info *action) +{ + struct action *a = NULL; + + if (!p || (action_id >= p->n_actions) || !action) + return -EINVAL; + + a = action_find_by_id(p, action_id); + if (!a) + return -EINVAL; + + strcpy(action->name, a->name); + action->n_args = a->st ? a->st->n_fields : 0; + return 0; +} + +int +rte_swx_ctl_action_arg_info_get(struct rte_swx_pipeline *p, + uint32_t action_id, + uint32_t action_arg_id, + struct rte_swx_ctl_action_arg_info *action_arg) +{ + struct action *a = NULL; + struct field *arg = NULL; + + if (!p || (action_id >= p->n_actions) || !action_arg) + return -EINVAL; + + a = action_find_by_id(p, action_id); + if (!a || !a->st || (action_arg_id >= a->st->n_fields)) + return -EINVAL; + + arg = &a->st->fields[action_arg_id]; + strcpy(action_arg->name, arg->name); + action_arg->n_bits = arg->n_bits; + + return 0; +} + +int +rte_swx_ctl_table_info_get(struct rte_swx_pipeline *p, + uint32_t table_id, + struct rte_swx_ctl_table_info *table) +{ + struct table *t = NULL; + + if (!p || !table) + return -EINVAL; + + t = table_find_by_id(p, table_id); + if (!t) + return -EINVAL; + + strcpy(table->name, t->name); + strcpy(table->args, t->args); + table->n_match_fields = t->n_fields; + table->n_actions = t->n_actions; + table->default_action_is_const = t->default_action_is_const; + table->size = t->size; + return 0; +} + +int +rte_swx_ctl_table_match_field_info_get(struct rte_swx_pipeline *p, + uint32_t table_id, + uint32_t match_field_id, + struct rte_swx_ctl_table_match_field_info *match_field) +{ + struct table *t; + struct match_field *f; + + if (!p || (table_id >= p->n_tables) || !match_field) + return -EINVAL; + + t = table_find_by_id(p, table_id); + if (!t || (match_field_id >= t->n_fields)) + return -EINVAL; + + f = &t->fields[match_field_id]; + match_field->match_type = f->match_type; + match_field->is_header = t->is_header; + match_field->n_bits = f->field->n_bits; + match_field->offset = f->field->offset; + + return 0; +} + +int +rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p, + uint32_t table_id, + uint32_t table_action_id, + struct rte_swx_ctl_table_action_info *table_action) +{ + struct table *t; + + if (!p || (table_id >= p->n_tables) || !table_action) + return -EINVAL; + + t = table_find_by_id(p, table_id); + if (!t || (table_action_id >= t->n_actions)) + return -EINVAL; + + table_action->action_id = t->actions[table_action_id]->id; + + return 0; +} + +int +rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p, + uint32_t table_id, + struct rte_swx_table_ops *table_ops, + int *is_stub) +{ + struct table *t; + + if (!p || (table_id >= p->n_tables)) + return -EINVAL; + + t = table_find_by_id(p, table_id); + if (!t) + return -EINVAL; + + if (t->type) { + if (table_ops) + memcpy(table_ops, &t->type->ops, sizeof(*table_ops)); + *is_stub = 0; + } else { + *is_stub = 1; + } + + return 0; +} + int rte_swx_pipeline_table_state_get(struct rte_swx_pipeline *p, struct rte_swx_table_state **table_state) @@ -6963,3 +7146,39 @@ rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p, p->table_state = table_state; return 0; } + +int +rte_swx_ctl_pipeline_port_in_stats_read(struct rte_swx_pipeline *p, + uint32_t port_id, + struct rte_swx_port_in_stats *stats) +{ + struct port_in *port; + + if (!p || !stats) + return -EINVAL; + + port = port_in_find(p, port_id); + if (!port) + return -EINVAL; + + port->type->ops.stats_read(port->obj, stats); + return 0; +} + +int +rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p, + uint32_t port_id, + struct rte_swx_port_out_stats *stats) +{ + struct port_out *port; + + if (!p || !stats) + return -EINVAL; + + port = port_out_find(p, port_id); + if (!port) + return -EINVAL; + + port->type->ops.stats_read(port->obj, stats); + return 0; +} -- 2.20.1