[V3,4/7] pipeline: support direct registers on the control path

Message ID 20220830185811.1843109-5-cristian.dumitrescu@intel.com (mailing list archive)
State Accepted, archived
Delegated to: Thomas Monjalon
Headers
Series pipeline: support direct registers and meters |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Cristian Dumitrescu Aug. 30, 2022, 6:58 p.m. UTC
  Add pipeline control path API to read/write direct registers. These
registers are identified by a table key, whose entry ID is used as the
index into the register array.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 lib/pipeline/rte_swx_ctl.h      |  52 +++++++
 lib/pipeline/rte_swx_pipeline.c | 255 ++++++++++++++++++++++++++++++++
 lib/pipeline/version.map        |   2 +
 3 files changed, 309 insertions(+)
  

Patch

diff --git a/lib/pipeline/rte_swx_ctl.h b/lib/pipeline/rte_swx_ctl.h
index 0694df557a..1b47820441 100644
--- a/lib/pipeline/rte_swx_ctl.h
+++ b/lib/pipeline/rte_swx_ctl.h
@@ -1237,6 +1237,58 @@  rte_swx_ctl_pipeline_regarray_write(struct rte_swx_pipeline *p,
 				   uint32_t regarray_index,
 				   uint64_t value);
 
+/**
+ * Register read with table key lookup
+ *
+ * @param[in] p
+ *   Pipeline handle.
+ * @param[in] regarray_name
+ *   Register array name.
+ * @param[in] table_name
+ *   Regular or learner table name.
+ * @param[in] table_key
+ *   Table key.
+ * @param[out] value
+ *   Current register value.
+ * @return
+ *   0 on success or the following error codes otherwise:
+ *   -EINVAL: Invalid argument;
+ *   -ENOMEM: Not enough memory.
+ */
+__rte_experimental
+int
+rte_swx_ctl_pipeline_regarray_read_with_key(struct rte_swx_pipeline *p,
+					    const char *regarray_name,
+					    const char *table_name,
+					    uint8_t *table_key,
+					    uint64_t *value);
+
+/**
+ * Register write with table key lookup
+ *
+ * @param[in] p
+ *   Pipeline handle.
+ * @param[in] regarray_name
+ *   Register array name.
+ * @param[in] table_name
+ *   Regular or learner table name.
+ * @param[in] table_key
+ *   Table key.
+ * @param[in] value
+ *   Value to be written to the register.
+ * @return
+ *   0 on success or the following error codes otherwise:
+ *   -EINVAL: Invalid argument;
+ *   -ENOMEM: Not enough memory.
+ */
+__rte_experimental
+int
+rte_swx_ctl_pipeline_regarray_write_with_key(struct rte_swx_pipeline *p,
+					     const char *regarray_name,
+					     const char *table_name,
+					     uint8_t *table_key,
+					     uint64_t value);
+
 /*
  * Meter Array Query and Configuration API.
  */
diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index ec8268b7f8..ab59e7ad79 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -8261,6 +8261,24 @@  rte_swx_pipeline_table_config(struct rte_swx_pipeline *p,
 	return status;
 }
 
+static uint32_t
+table_params_offset_get(struct table *table)
+{
+	struct field *first;
+	uint32_t i;
+
+	first = table->fields[0].field;
+
+	for (i = 1; i < table->n_fields; i++) {
+		struct field *f = table->fields[i].field;
+
+		if (f->offset < first->offset)
+			first = f;
+	}
+
+	return first->offset / 8;
+}
+
 static struct rte_swx_table_params *
 table_params_get(struct table *table)
 {
@@ -9217,6 +9235,24 @@  rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
 	return status;
 }
 
+static uint32_t
+learner_params_offset_get(struct learner *l)
+{
+	struct field *first;
+	uint32_t i;
+
+	first = l->fields[0];
+
+	for (i = 1; i < l->n_fields; i++) {
+		struct field *f = l->fields[i];
+
+		if (f->offset < first->offset)
+			first = f;
+	}
+
+	return first->offset / 8;
+}
+
 static void
 learner_params_free(struct rte_swx_table_learner_params *params)
 {
@@ -11101,6 +11137,225 @@  rte_swx_ctl_pipeline_mirroring_session_set(struct rte_swx_pipeline *p,
 	return 0;
 }
 
+static int
+rte_swx_ctl_pipeline_table_lookup(struct rte_swx_pipeline *p,
+				  const char *table_name,
+				  uint8_t *key,
+				  uint64_t *action_id,
+				  uint8_t **action_data,
+				  size_t *entry_id,
+				  int *hit)
+{
+	struct table *t;
+	void *mailbox = NULL;
+
+	/* Check input arguments. */
+	if (!p ||
+	    !p->build_done ||
+	    !table_name ||
+	    !table_name[0] ||
+	    !key ||
+	    !entry_id ||
+	    !hit)
+		return -EINVAL;
+
+	/* Find the table. */
+	t = table_find(p, table_name);
+	if (!t)
+		return -EINVAL;
+
+	if (!t->type) {
+		*hit = 0;
+		return 0;
+	}
+
+	/* Setup mailbox.  */
+	if (t->type->ops.mailbox_size_get) {
+		uint64_t mailbox_size;
+
+		mailbox_size = t->type->ops.mailbox_size_get();
+		if (mailbox_size) {
+			mailbox = calloc(1, mailbox_size);
+			if (!mailbox)
+				return -ENOMEM;
+		}
+	}
+
+	/* Table lookup operation. */
+	key -= table_params_offset_get(t);
+
+	for ( ; ; ) {
+		struct rte_swx_table_state *ts = &p->table_state[t->id];
+		int done;
+
+		done = t->type->ops.lkp(ts->obj,
+					mailbox,
+					&key,
+					action_id,
+					action_data,
+					entry_id,
+					hit);
+		if (done)
+			break;
+	}
+
+	/* Free mailbox. */
+	free(mailbox);
+
+	return 0;
+}
+
+static int
+rte_swx_ctl_pipeline_learner_lookup(struct rte_swx_pipeline *p,
+				    const char *learner_name,
+				    uint8_t *key,
+				    uint64_t *action_id,
+				    uint8_t **action_data,
+				    size_t *entry_id,
+				    int *hit)
+{
+	struct learner *l;
+	void *mailbox = NULL;
+	uint64_t mailbox_size, time;
+
+	/* Check input arguments. */
+	if (!p ||
+	    !p->build_done ||
+	    !learner_name ||
+	    !learner_name[0] ||
+	    !key ||
+	    !entry_id ||
+	    !hit)
+		return -EINVAL;
+
+	/* Find the learner table. */
+	l = learner_find(p, learner_name);
+	if (!l)
+		return -EINVAL;
+
+	/* Setup mailbox.  */
+	mailbox_size = rte_swx_table_learner_mailbox_size_get();
+	if (mailbox_size) {
+		mailbox = calloc(1, mailbox_size);
+		if (!mailbox)
+			return -ENOMEM;
+	}
+
+	/* Learner table lookup operation. */
+	key -= learner_params_offset_get(l);
+
+	time = rte_get_tsc_cycles();
+
+	for ( ; ; ) {
+		uint32_t pos = p->n_tables + p->n_selectors + l->id;
+		struct rte_swx_table_state *ts = &p->table_state[pos];
+		int done;
+
+		done = rte_swx_table_learner_lookup(ts->obj,
+						    mailbox,
+						    time,
+						    &key,
+						    action_id,
+						    action_data,
+						    entry_id,
+						    hit);
+		if (done)
+			break;
+	}
+
+	/* Free mailbox. */
+	free(mailbox);
+
+	return 0;
+}
+
+static int
+rte_swx_ctl_pipeline_table_entry_id_get(struct rte_swx_pipeline *p,
+					const char *table_name,
+					uint8_t *table_key,
+					size_t *table_entry_id)
+{
+	struct table *t;
+	struct learner *l;
+	uint64_t action_id;
+	uint8_t *action_data;
+	size_t entry_id = 0;
+	int hit = 0, status;
+
+	/* Check input arguments. */
+	if (!p ||
+	    !p->build_done ||
+	    !table_name ||
+	    !table_name[0] ||
+	    !table_key ||
+	    !table_entry_id)
+		return -EINVAL;
+
+	t = table_find(p, table_name);
+	l = learner_find(p, table_name);
+	if (!t && !l)
+		return -EINVAL;
+
+	/* Table lookup operation. */
+	if (t)
+		status = rte_swx_ctl_pipeline_table_lookup(p,
+							   table_name,
+							   table_key,
+							   &action_id,
+							   &action_data,
+							   &entry_id,
+							   &hit);
+	else
+		status = rte_swx_ctl_pipeline_learner_lookup(p,
+							     table_name,
+							     table_key,
+							     &action_id,
+							     &action_data,
+							     &entry_id,
+							     &hit);
+	if (status)
+		return status;
+
+	/* Reserve entry ID 0 for the table default entry. */
+	*table_entry_id = hit ? (1 + entry_id) : 0;
+
+	return 0;
+}
+
+int
+rte_swx_ctl_pipeline_regarray_read_with_key(struct rte_swx_pipeline *p,
+					    const char *regarray_name,
+					    const char *table_name,
+					    uint8_t *table_key,
+					    uint64_t *value)
+{
+	size_t entry_id = 0;
+	int status;
+
+	status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
+	if (status)
+		return status;
+
+	return rte_swx_ctl_pipeline_regarray_read(p, regarray_name, entry_id, value);
+}
+
+int
+rte_swx_ctl_pipeline_regarray_write_with_key(struct rte_swx_pipeline *p,
+					     const char *regarray_name,
+					     const char *table_name,
+					     uint8_t *table_key,
+					     uint64_t value)
+{
+	size_t entry_id = 0;
+	int status;
+
+	status = rte_swx_ctl_pipeline_table_entry_id_get(p, table_name, table_key, &entry_id);
+	if (status)
+		return status;
+
+	return rte_swx_ctl_pipeline_regarray_write(p, regarray_name, entry_id, value);
+}
+
 /*
  * Pipeline compilation.
  */
diff --git a/lib/pipeline/version.map b/lib/pipeline/version.map
index 16806e6802..8ed92042d6 100644
--- a/lib/pipeline/version.map
+++ b/lib/pipeline/version.map
@@ -147,6 +147,8 @@  EXPERIMENTAL {
 
 	#added in 22.11
 	rte_swx_ctl_pipeline_find;
+	rte_swx_ctl_pipeline_regarray_read_with_key;
+	rte_swx_ctl_pipeline_regarray_write_with_key;
 	rte_swx_pipeline_build_from_lib;
 	rte_swx_pipeline_codegen;
 	rte_swx_pipeline_find;