pipeline: add SWX pipeline query API
authorCristian Dumitrescu <cristian.dumitrescu@intel.com>
Thu, 1 Oct 2020 10:19:57 +0000 (11:19 +0100)
committerDavid Marchand <david.marchand@redhat.com>
Thu, 1 Oct 2020 16:43:08 +0000 (18:43 +0200)
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 <cristian.dumitrescu@intel.com>
lib/librte_pipeline/rte_pipeline_version.map
lib/librte_pipeline/rte_swx_ctl.h
lib/librte_pipeline/rte_swx_pipeline.c

index 861682e..b1e0ab6 100644 (file)
@@ -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;
index c824ab5..54b895f 100644 (file)
@@ -18,8 +18,321 @@ extern "C" {
 
 #include <rte_compat.h>
 
+#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.
  */
index 77eae19..da69bab 100644 (file)
@@ -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;
+}