All of lore.kernel.org
 help / color / mirror / Atom feed
From: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
To: dev@dpdk.org
Cc: Yogesh Jangra <yogesh.jangra@intel.com>
Subject: [dpdk-dev] [PATCH] pipeline: add table statistics
Date: Sat, 17 Apr 2021 00:46:41 +0100	[thread overview]
Message-ID: <20210416234641.16304-1-cristian.dumitrescu@intel.com> (raw)

Add support for table statistics for the SWX pipeline. For each table,
we maintain a counter for lookup hit packets, one for lookup miss
packets and one packet counter for each table action.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 examples/pipeline/cli.c                | 54 +++++++++++++++++++++++-
 lib/librte_pipeline/rte_swx_ctl.h      | 38 +++++++++++++++++
 lib/librte_pipeline/rte_swx_pipeline.c | 57 +++++++++++++++++++++++++-
 lib/librte_pipeline/version.map        |  1 +
 4 files changed, 148 insertions(+), 2 deletions(-)

diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index ef47febaa..215dd8e85 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -1802,7 +1802,7 @@ cmd_pipeline_stats(char **tokens,
 		out += strlen(out);
 	}
 
-	snprintf(out, out_size, "Output ports:\n");
+	snprintf(out, out_size, "\nOutput ports:\n");
 	out_size -= strlen(out);
 	out += strlen(out);
 
@@ -1818,6 +1818,58 @@ cmd_pipeline_stats(char **tokens,
 		out_size -= strlen(out);
 		out += strlen(out);
 	}
+
+	snprintf(out, out_size, "\nTables:\n");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	for (i = 0; i < info.n_tables; i++) {
+		struct rte_swx_ctl_table_info table_info;
+		uint64_t n_pkts_action[info.n_actions];
+		struct rte_swx_table_stats stats = {
+			.n_pkts_hit = 0,
+			.n_pkts_miss = 0,
+			.n_pkts_action = n_pkts_action,
+		};
+		uint32_t j;
+
+		status = rte_swx_ctl_table_info_get(p->p, i, &table_info);
+		if (status) {
+			snprintf(out, out_size, "Table info get error.");
+			return;
+		}
+
+		status = rte_swx_ctl_pipeline_table_stats_read(p->p, table_info.name, &stats);
+		if (status) {
+			snprintf(out, out_size, "Table stats read error.");
+			return;
+		}
+
+		snprintf(out, out_size, "\tTable %s:\n"
+			"\t\tHit (packets): %" PRIu64 "\n"
+			"\t\tMiss (packets): %" PRIu64 "\n",
+			table_info.name,
+			stats.n_pkts_hit,
+			stats.n_pkts_miss);
+		out_size -= strlen(out);
+		out += strlen(out);
+
+		for (j = 0; j < info.n_actions; j++) {
+			struct rte_swx_ctl_action_info action_info;
+
+			status = rte_swx_ctl_action_info_get(p->p, j, &action_info);
+			if (status) {
+				snprintf(out, out_size, "Action info get error.");
+				return;
+			}
+
+			snprintf(out, out_size, "\t\tAction %s (packets): %" PRIu64 "\n",
+				action_info.name,
+				stats.n_pkts_action[j]);
+			out_size -= strlen(out);
+			out += strlen(out);
+		}
+	}
 }
 
 static const char cmd_thread_pipeline_enable_help[] =
diff --git a/lib/librte_pipeline/rte_swx_ctl.h b/lib/librte_pipeline/rte_swx_ctl.h
index 4e5befb50..dee788be8 100644
--- a/lib/librte_pipeline/rte_swx_ctl.h
+++ b/lib/librte_pipeline/rte_swx_ctl.h
@@ -347,6 +347,44 @@ rte_swx_ctl_table_ops_get(struct rte_swx_pipeline *p,
 			  struct rte_swx_table_ops *table_ops,
 			  int *is_stub);
 
+/** Table statistics. */
+struct rte_swx_table_stats {
+	/** Number of packets with lookup hit. */
+	uint64_t n_pkts_hit;
+
+	/** Number of packets with lookup miss. */
+	uint64_t n_pkts_miss;
+
+	/** Number of packets (with either lookup hit or miss) per pipeline
+	 * action. Array of pipeline *n_actions* elements indedex by the
+	 * pipeline-level *action_id*, therefore this array has the same size
+	 * for all the tables within the same pipeline.
+	 */
+	uint64_t *n_pkts_action;
+};
+
+/**
+ * Table statistics counters read
+ *
+ * @param[in] p
+ *   Pipeline handle.
+ * @param[in] table_name
+ *   Table name.
+ * @param[out] stats
+ *   Table stats. Must point to a pre-allocated structure. The *n_pkts_action*
+ *   field also needs to be pre-allocated as array of pipeline *n_actions*
+ *   elements. The pipeline actions that are not valid for the current table
+ *   have their associated *n_pkts_action* element always set to zero.
+ * @return
+ *   0 on success or the following error codes otherwise:
+ *   -EINVAL: Invalid argument.
+ */
+__rte_experimental
+int
+rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
+				      const char *table_name,
+				      struct rte_swx_table_stats *stats);
+
 /*
  * Table Update API.
  */
diff --git a/lib/librte_pipeline/rte_swx_pipeline.c b/lib/librte_pipeline/rte_swx_pipeline.c
index aeb445755..4e358bbda 100644
--- a/lib/librte_pipeline/rte_swx_pipeline.c
+++ b/lib/librte_pipeline/rte_swx_pipeline.c
@@ -789,6 +789,11 @@ struct table_runtime {
 	uint8_t **key;
 };
 
+struct table_statistics {
+	uint64_t n_pkts_hit[2]; /* 0 = Miss, 1 = Hit. */
+	uint64_t *n_pkts_action;
+};
+
 /*
  * Register array.
  */
@@ -1311,6 +1316,7 @@ struct rte_swx_pipeline {
 	struct port_out_runtime *out;
 	struct instruction **action_instructions;
 	struct rte_swx_table_state *table_state;
+	struct table_statistics *table_stats;
 	struct regarray_runtime *regarray_runtime;
 	struct metarray_runtime *metarray_runtime;
 	struct instruction *instructions;
@@ -3473,7 +3479,8 @@ instr_table_exec(struct rte_swx_pipeline *p)
 	uint32_t table_id = ip->table.table_id;
 	struct rte_swx_table_state *ts = &t->table_state[table_id];
 	struct table_runtime *table = &t->tables[table_id];
-	uint64_t action_id;
+	struct table_statistics *stats = &p->table_stats[table_id];
+	uint64_t action_id, n_pkts_hit, n_pkts_action;
 	uint8_t *action_data;
 	int done, hit;
 
@@ -3496,6 +3503,8 @@ instr_table_exec(struct rte_swx_pipeline *p)
 
 	action_id = hit ? action_id : ts->default_action_id;
 	action_data = hit ? action_data : ts->default_action_data;
+	n_pkts_hit = stats->n_pkts_hit[hit];
+	n_pkts_action = stats->n_pkts_action[action_id];
 
 	TRACE("[Thread %2u] table %u (%s, action %u)\n",
 	      p->thread_id,
@@ -3506,6 +3515,8 @@ instr_table_exec(struct rte_swx_pipeline *p)
 	t->action_id = action_id;
 	t->structs[0] = action_data;
 	t->hit = hit;
+	stats->n_pkts_hit[hit] = n_pkts_hit + 1;
+	stats->n_pkts_action[action_id] = n_pkts_action + 1;
 
 	/* Thread. */
 	thread_ip_action_call(p, t, action_id);
@@ -9537,6 +9548,16 @@ table_build(struct rte_swx_pipeline *p)
 {
 	uint32_t i;
 
+	/* Per pipeline: table statistics. */
+	p->table_stats = calloc(p->n_tables, sizeof(struct table_statistics));
+	CHECK(p->table_stats, ENOMEM);
+
+	for (i = 0; i < p->n_tables; i++) {
+		p->table_stats[i].n_pkts_action = calloc(p->n_actions, sizeof(uint64_t));
+		CHECK(p->table_stats[i].n_pkts_action, ENOMEM);
+	}
+
+	/* Per thread: table runt-time. */
 	for (i = 0; i < RTE_SWX_PIPELINE_THREADS_MAX; i++) {
 		struct thread *t = &p->threads[i];
 		struct table *table;
@@ -9595,6 +9616,13 @@ table_build_free(struct rte_swx_pipeline *p)
 		free(t->tables);
 		t->tables = NULL;
 	}
+
+	if (p->table_stats) {
+		for (i = 0; i < p->n_tables; i++)
+			free(p->table_stats[i].n_pkts_action);
+
+		free(p->table_stats);
+	}
 }
 
 static void
@@ -10350,6 +10378,33 @@ rte_swx_ctl_pipeline_port_out_stats_read(struct rte_swx_pipeline *p,
 	return 0;
 }
 
+int
+rte_swx_ctl_pipeline_table_stats_read(struct rte_swx_pipeline *p,
+				      const char *table_name,
+				      struct rte_swx_table_stats *stats)
+{
+	struct table *table;
+	struct table_statistics *table_stats;
+
+	if (!p || !table_name || !table_name[0] || !stats || !stats->n_pkts_action)
+		return -EINVAL;
+
+	table = table_find(p, table_name);
+	if (!table)
+		return -EINVAL;
+
+	table_stats = &p->table_stats[table->id];
+
+	memcpy(&stats->n_pkts_action,
+	       &table_stats->n_pkts_action,
+	       p->n_actions * sizeof(uint64_t));
+
+	stats->n_pkts_hit = table_stats->n_pkts_hit[1];
+	stats->n_pkts_miss = table_stats->n_pkts_hit[0];
+
+	return 0;
+}
+
 int
 rte_swx_ctl_regarray_info_get(struct rte_swx_pipeline *p,
 			      uint32_t regarray_id,
diff --git a/lib/librte_pipeline/version.map b/lib/librte_pipeline/version.map
index 2049d6d69..a4d7d9788 100644
--- a/lib/librte_pipeline/version.map
+++ b/lib/librte_pipeline/version.map
@@ -112,6 +112,7 @@ EXPERIMENTAL {
 	rte_swx_ctl_meter_stats_read;
 	rte_swx_ctl_pipeline_regarray_read;
 	rte_swx_ctl_pipeline_regarray_write;
+	rte_swx_ctl_pipeline_table_stats_read;
 	rte_swx_ctl_regarray_info_get;
 	rte_swx_pipeline_metarray_config;
 	rte_swx_pipeline_regarray_config;
-- 
2.17.1


             reply	other threads:[~2021-04-16 23:46 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-16 23:46 Cristian Dumitrescu [this message]
2021-04-20  0:29 ` [dpdk-dev] [PATCH] pipeline: add table statistics Thomas Monjalon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210416234641.16304-1-cristian.dumitrescu@intel.com \
    --to=cristian.dumitrescu@intel.com \
    --cc=dev@dpdk.org \
    --cc=yogesh.jangra@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.