From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124])
	by inbox.dpdk.org (Postfix) with ESMTP id 1F6B3A0554;
	Fri, 26 Aug 2022 12:36:46 +0200 (CEST)
Received: from [217.70.189.124] (localhost [127.0.0.1])
	by mails.dpdk.org (Postfix) with ESMTP id 979E942B6F;
	Fri, 26 Aug 2022 12:36:18 +0200 (CEST)
Received: from mga06.intel.com (mga06b.intel.com [134.134.136.31])
 by mails.dpdk.org (Postfix) with ESMTP id E9A24410D2
 for <dev@dpdk.org>; Fri, 26 Aug 2022 12:36:12 +0200 (CEST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple;
 d=intel.com; i=@intel.com; q=dns/txt; s=Intel;
 t=1661510173; x=1693046173;
 h=from:to:subject:date:message-id:in-reply-to:references:
 mime-version:content-transfer-encoding;
 bh=5raGhCc4aHNDcFVoUm+gNSoxFRD4A7HZwZivjAN4MMo=;
 b=RWG3kyInAWpNqerSg44aj7Qhm6UYs8yL62hbV2fiQ3H0eNZuWKbVAblw
 thd9nkm5u/kTJRNLz1lpxsaAVAjGfnC+UL4JhyeVShB+F4VEGrsj6Auov
 xUmbmN+LHFWLJHZi2GHKJYHzLHQPpqQI29D+OBk7i1/8tRK1bvpsmS+M1
 jwdSznH1XhjLGb5veLSc+Wm9515G5Fn1ulJMcek54x6S5xlJ6/2AMBbtf
 uBAPExkSXbj4+sZY8Gzy5/9TgtKqhANwAk7jb61OjZVoPn2R2KBU4pfr+
 qn/0Svf3NaUm9wzpAAPTOK859kNSr/F7ALrh6vJywak6m0PmPB/yZr9JL g==;
X-IronPort-AV: E=McAfee;i="6500,9779,10450"; a="356194331"
X-IronPort-AV: E=Sophos;i="5.93,265,1654585200"; d="scan'208";a="356194331"
Received: from fmsmga008.fm.intel.com ([10.253.24.58])
 by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;
 26 Aug 2022 03:36:12 -0700
X-ExtLoop1: 1
X-IronPort-AV: E=Sophos;i="5.93,265,1654585200"; d="scan'208";a="671414298"
Received: from silpixa00400573.ir.intel.com (HELO
 silpixa00400573.ger.corp.intel.com.) ([10.237.223.157])
 by fmsmga008.fm.intel.com with ESMTP; 26 Aug 2022 03:36:11 -0700
From: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
To: dev@dpdk.org
Subject: [PATCH 7/7] examples/pipeline: add CLI commands for direct meters
Date: Fri, 26 Aug 2022 10:36:05 +0000
Message-Id: <20220826103605.1579589-8-cristian.dumitrescu@intel.com>
X-Mailer: git-send-email 2.34.1
In-Reply-To: <20220826103605.1579589-1-cristian.dumitrescu@intel.com>
References: <20220826103605.1579589-1-cristian.dumitrescu@intel.com>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: DPDK patches and discussions <dev.dpdk.org>
List-Unsubscribe: <https://mails.dpdk.org/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://mails.dpdk.org/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <https://mails.dpdk.org/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
Errors-To: dev-bounces@dpdk.org

Add the CLI command support for managing direct meters.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 examples/pipeline/cli.c              | 414 ++++++++++++++++++++-------
 examples/pipeline/examples/meter.cli |   2 +-
 2 files changed, 309 insertions(+), 107 deletions(-)

diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index 72998f580b..4ddece3571 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -2105,8 +2105,9 @@ cmd_pipeline_meter_profile_delete(char **tokens,
 }
 
 static const char cmd_pipeline_meter_reset_help[] =
-"pipeline <pipeline_name> meter <meter_array_name> from <index0> to <index1> "
-	"reset\n";
+"pipeline <pipeline_name> meter <meter_array_name> reset"
+	"index from <index0> to <index1>"
+	" | table <table_name> match <field0> ...\n";
 
 static void
 cmd_pipeline_meter_reset(char **tokens,
@@ -2116,16 +2117,18 @@ cmd_pipeline_meter_reset(char **tokens,
 	void *obj __rte_unused)
 {
 	struct rte_swx_pipeline *p;
-	const char *name;
-	uint32_t idx0 = 0, idx1 = 0;
+	struct rte_swx_ctl_pipeline *ctl;
+	const char *pipeline_name, *name;
 
-	if (n_tokens != 9) {
+	if (n_tokens < 6) {
 		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
 		return;
 	}
 
-	p = rte_swx_pipeline_find(tokens[1]);
-	if (!p) {
+	pipeline_name = tokens[1];
+	p = rte_swx_pipeline_find(pipeline_name);
+	ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+	if (!p || !ctl) {
 		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
 		return;
 	}
@@ -2137,45 +2140,96 @@ cmd_pipeline_meter_reset(char **tokens,
 
 	name = tokens[3];
 
-	if (strcmp(tokens[4], "from")) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
+	if (strcmp(tokens[4], "reset")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "reset");
 		return;
 	}
 
-	if (parser_read_uint32(&idx0, tokens[5])) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "index0");
-		return;
-	}
+	/* index. */
+	if (!strcmp(tokens[5], "index")) {
+		uint32_t idx0 = 0, idx1 = 0;
 
-	if (strcmp(tokens[6], "to")) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
-		return;
-	}
+		if (n_tokens != 10) {
+			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+			return;
+		}
 
-	if (parser_read_uint32(&idx1, tokens[7]) || (idx1 < idx0)) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "index1");
-		return;
-	}
+		if (strcmp(tokens[6], "from")) {
+			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
+			return;
+		}
+
+		if (parser_read_uint32(&idx0, tokens[7])) {
+			snprintf(out, out_size, MSG_ARG_INVALID, "index0");
+			return;
+		}
+
+		if (strcmp(tokens[8], "to")) {
+			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
+			return;
+		}
+
+		if (parser_read_uint32(&idx1, tokens[9]) || (idx1 < idx0)) {
+			snprintf(out, out_size, MSG_ARG_INVALID, "index1");
+			return;
+		}
+
+		for ( ; idx0 <= idx1; idx0++) {
+			int status;
+
+			status = rte_swx_ctl_meter_reset(p, name, idx0);
+			if (status) {
+				snprintf(out, out_size, "Command failed for index %u.\n", idx0);
+				return;
+			}
+		}
 
-	if (strcmp(tokens[8], "reset")) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "reset");
 		return;
 	}
 
-	for ( ; idx0 <= idx1; idx0++) {
+	/* table. */
+	if (!strcmp(tokens[5], "table")) {
+		struct rte_swx_table_entry *entry;
+		char *table_name;
 		int status;
 
-		status = rte_swx_ctl_meter_reset(p, name, idx0);
+		if (n_tokens < 9) {
+			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+			return;
+		}
+
+		table_name = tokens[6];
+
+		if (strcmp(tokens[7], "match")) {
+			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
+			return;
+		}
+
+		entry = parse_table_entry(ctl, table_name, &tokens[7], n_tokens - 7);
+		if (!entry) {
+			snprintf(out, out_size, "Invalid match tokens.\n");
+			return;
+		}
+
+		status = rte_swx_ctl_meter_reset_with_key(p, name, table_name, entry->key);
+		table_entry_free(entry);
 		if (status) {
-			snprintf(out, out_size, "Command failed for index %u.\n", idx0);
+			snprintf(out, out_size, "Command failed.\n");
 			return;
 		}
+
+		return;
 	}
+
+	/* anything else. */
+	snprintf(out, out_size, "Invalid token %s\n.", tokens[5]);
+	return;
 }
 
 static const char cmd_pipeline_meter_set_help[] =
-"pipeline <pipeline_name> meter <meter_array_name> from <index0> to <index1> "
-	"set profile <profile_name>\n";
+"pipeline <pipeline_name> meter <meter_array_name> set profile <profile_name>"
+	"index from <index0> to <index1>"
+	" | table <table_name> match <field0> ...\n";
 
 static void
 cmd_pipeline_meter_set(char **tokens,
@@ -2185,16 +2239,18 @@ cmd_pipeline_meter_set(char **tokens,
 	void *obj __rte_unused)
 {
 	struct rte_swx_pipeline *p;
-	const char *name, *profile_name;
-	uint32_t idx0 = 0, idx1 = 0;
+	struct rte_swx_ctl_pipeline *ctl;
+	const char *pipeline_name, *name, *profile_name;
 
-	if (n_tokens != 11) {
+	if (n_tokens < 8) {
 		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
 		return;
 	}
 
-	p = rte_swx_pipeline_find(tokens[1]);
-	if (!p) {
+	pipeline_name = tokens[1];
+	p = rte_swx_pipeline_find(pipeline_name);
+	ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+	if (!p || !ctl) {
 		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
 		return;
 	}
@@ -2206,52 +2262,107 @@ cmd_pipeline_meter_set(char **tokens,
 
 	name = tokens[3];
 
-	if (strcmp(tokens[4], "from")) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
+	if (strcmp(tokens[4], "set")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "set");
 		return;
 	}
 
-	if (parser_read_uint32(&idx0, tokens[5])) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "index0");
+	if (strcmp(tokens[5], "profile")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
 		return;
 	}
 
-	if (strcmp(tokens[6], "to")) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
-		return;
-	}
+	profile_name = tokens[6];
 
-	if (parser_read_uint32(&idx1, tokens[7]) || (idx1 < idx0)) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "index1");
-		return;
-	}
+	/* index. */
+	if (!strcmp(tokens[7], "index")) {
+		uint32_t idx0 = 0, idx1 = 0;
 
-	if (strcmp(tokens[8], "set")) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "set");
-		return;
-	}
+		if (n_tokens != 12) {
+			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+			return;
+		}
+
+		if (strcmp(tokens[8], "from")) {
+			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
+			return;
+		}
+
+		if (parser_read_uint32(&idx0, tokens[9])) {
+			snprintf(out, out_size, MSG_ARG_INVALID, "index0");
+			return;
+		}
+
+		if (strcmp(tokens[10], "to")) {
+			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
+			return;
+		}
+
+		if (parser_read_uint32(&idx1, tokens[11]) || (idx1 < idx0)) {
+			snprintf(out, out_size, MSG_ARG_INVALID, "index1");
+			return;
+		}
+
+		for ( ; idx0 <= idx1; idx0++) {
+			int status;
+
+			status = rte_swx_ctl_meter_set(p, name, idx0, profile_name);
+			if (status) {
+				snprintf(out, out_size, "Command failed for index %u.\n", idx0);
+				return;
+			}
+		}
 
-	if (strcmp(tokens[9], "profile")) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
 		return;
 	}
 
-	profile_name = tokens[10];
-
-	for ( ; idx0 <= idx1; idx0++) {
+	/* table. */
+	if (!strcmp(tokens[7], "table")) {
+		struct rte_swx_table_entry *entry;
+		char *table_name;
 		int status;
 
-		status = rte_swx_ctl_meter_set(p, name, idx0, profile_name);
+		if (n_tokens < 11) {
+			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+			return;
+		}
+
+		table_name = tokens[8];
+
+		if (strcmp(tokens[9], "match")) {
+			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
+			return;
+		}
+
+		entry = parse_table_entry(ctl, table_name, &tokens[9], n_tokens - 9);
+		if (!entry) {
+			snprintf(out, out_size, "Invalid match tokens.\n");
+			return;
+		}
+
+		status = rte_swx_ctl_meter_set_with_key(p,
+							name,
+							table_name,
+							entry->key,
+							profile_name);
+		table_entry_free(entry);
 		if (status) {
-			snprintf(out, out_size, "Command failed for index %u.\n", idx0);
+			snprintf(out, out_size, "Command failed.\n");
 			return;
 		}
+
+		return;
 	}
+
+	/* anything else. */
+	snprintf(out, out_size, "Invalid token %s\n.", tokens[7]);
+	return;
 }
 
 static const char cmd_pipeline_meter_stats_help[] =
-"pipeline <pipeline_name> meter <meter_array_name> from <index0> to <index1> "
-	"stats\n";
+"pipeline <pipeline_name> meter <meter_array_name> stats"
+	"index from <index0> to <index1>"
+	" | table <table_name> match <field0> ...\n";
 
 static void
 cmd_pipeline_meter_stats(char **tokens,
@@ -2262,16 +2373,18 @@ cmd_pipeline_meter_stats(char **tokens,
 {
 	struct rte_swx_ctl_meter_stats stats;
 	struct rte_swx_pipeline *p;
-	const char *name;
-	uint32_t idx0 = 0, idx1 = 0;
+	struct rte_swx_ctl_pipeline *ctl;
+	const char *pipeline_name, *name;
 
-	if (n_tokens != 9) {
+	if (n_tokens != 6) {
 		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
 		return;
 	}
 
-	p = rte_swx_pipeline_find(tokens[1]);
-	if (!p) {
+	pipeline_name = tokens[1];
+	p = rte_swx_pipeline_find(pipeline_name);
+	ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+	if (!p || !ctl) {
 		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
 		return;
 	}
@@ -2283,68 +2396,151 @@ cmd_pipeline_meter_stats(char **tokens,
 
 	name = tokens[3];
 
-	if (strcmp(tokens[4], "from")) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
+	if (strcmp(tokens[4], "stats")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
 		return;
 	}
 
-	if (parser_read_uint32(&idx0, tokens[5])) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "index0");
-		return;
-	}
+	/* index. */
+	if (!strcmp(tokens[5], "index")) {
+		uint32_t idx0 = 0, idx1 = 0;
 
-	if (strcmp(tokens[6], "to")) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
-		return;
-	}
+		if (n_tokens != 10) {
+			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+			return;
+		}
 
-	if (parser_read_uint32(&idx1, tokens[7]) || (idx1 < idx0)) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "index1");
-		return;
-	}
+		if (strcmp(tokens[6], "from")) {
+			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
+			return;
+		}
+
+		if (parser_read_uint32(&idx0, tokens[7])) {
+			snprintf(out, out_size, MSG_ARG_INVALID, "index0");
+			return;
+		}
+
+		if (strcmp(tokens[8], "to")) {
+			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
+			return;
+		}
+
+		if (parser_read_uint32(&idx1, tokens[9]) || (idx1 < idx0)) {
+			snprintf(out, out_size, MSG_ARG_INVALID, "index1");
+			return;
+		}
+
+		/* Table header. */
+		snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n",
+			 "-------",
+			 "----------------", "----------------", "----------------",
+			 "----------------", "----------------", "----------------");
+		out_size -= strlen(out);
+		out += strlen(out);
+
+		snprintf(out, out_size, "| %4s | %16s | %16s | %16s | %16s | %16s | %16s |\n",
+			 "METER #",
+			 "GREEN (packets)", "YELLOW (packets)", "RED (packets)",
+			 "GREEN (bytes)", "YELLOW (bytes)", "RED (bytes)");
+		out_size -= strlen(out);
+		out += strlen(out);
+
+		snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n",
+			 "-------",
+			 "----------------", "----------------", "----------------",
+			 "----------------", "----------------", "----------------");
+		out_size -= strlen(out);
+		out += strlen(out);
+
+		/* Table rows. */
+		for ( ; idx0 <= idx1; idx0++) {
+			int status;
+
+			status = rte_swx_ctl_meter_stats_read(p, name, idx0, &stats);
+			if (status) {
+				snprintf(out, out_size, "Pipeline meter stats error at index %u.\n", idx0);
+				out_size -= strlen(out);
+				out += strlen(out);
+				return;
+			}
+
+			snprintf(out, out_size, "| %7d | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64
+				 " | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64 " |\n",
+				 idx0,
+				 stats.n_pkts[RTE_COLOR_GREEN],
+				 stats.n_pkts[RTE_COLOR_YELLOW],
+				 stats.n_pkts[RTE_COLOR_RED],
+				 stats.n_bytes[RTE_COLOR_GREEN],
+				 stats.n_bytes[RTE_COLOR_YELLOW],
+				 stats.n_bytes[RTE_COLOR_RED]);
+			out_size -= strlen(out);
+			out += strlen(out);
+		}
 
-	if (strcmp(tokens[8], "stats")) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
 		return;
 	}
 
-	/* Table header. */
-	snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n",
-		 "-------",
-		 "----------------", "----------------", "----------------",
-		 "----------------", "----------------", "----------------");
-	out_size -= strlen(out);
-	out += strlen(out);
+	/* table. */
+	if (!strcmp(tokens[5], "table")) {
+		struct rte_swx_table_entry *entry;
+		char *table_name;
+		int status;
 
-	snprintf(out, out_size, "| %4s | %16s | %16s | %16s | %16s | %16s | %16s |\n",
-		 "METER #",
-		 "GREEN (packets)", "YELLOW (packets)", "RED (packets)",
-		 "GREEN (bytes)", "YELLOW (bytes)", "RED (bytes)");
-	out_size -= strlen(out);
-	out += strlen(out);
+		if (n_tokens < 9) {
+			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+			return;
+		}
 
-	snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n",
-		 "-------",
-		 "----------------", "----------------", "----------------",
-		 "----------------", "----------------", "----------------");
-	out_size -= strlen(out);
-	out += strlen(out);
+		table_name = tokens[6];
 
-	/* Table rows. */
-	for ( ; idx0 <= idx1; idx0++) {
-		int status;
+		if (strcmp(tokens[7], "match")) {
+			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
+			return;
+		}
+
+		entry = parse_table_entry(ctl, table_name, &tokens[7], n_tokens - 7);
+		if (!entry) {
+			snprintf(out, out_size, "Invalid match tokens.\n");
+			return;
+		}
 
-		status = rte_swx_ctl_meter_stats_read(p, name, idx0, &stats);
+		status = rte_swx_ctl_meter_stats_read_with_key(p,
+							name,
+							table_name,
+							entry->key,
+							&stats);
+		table_entry_free(entry);
 		if (status) {
-			snprintf(out, out_size, "Pipeline meter stats error at index %u.\n", idx0);
-			out_size -= strlen(out);
-			out += strlen(out);
+			snprintf(out, out_size, "Command failed.\n");
 			return;
 		}
 
+		/* Table header. */
+		snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n",
+			 "-------",
+			 "----------------", "----------------", "----------------",
+			 "----------------", "----------------", "----------------");
+		out_size -= strlen(out);
+		out += strlen(out);
+
+		snprintf(out, out_size, "| %4s | %16s | %16s | %16s | %16s | %16s | %16s |\n",
+			 "METER #",
+			 "GREEN (packets)", "YELLOW (packets)", "RED (packets)",
+			 "GREEN (bytes)", "YELLOW (bytes)", "RED (bytes)");
+		out_size -= strlen(out);
+		out += strlen(out);
+
+		snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n",
+			 "-------",
+			 "----------------", "----------------", "----------------",
+			 "----------------", "----------------", "----------------");
+		out_size -= strlen(out);
+		out += strlen(out);
+
+		/* Table row. */
 		snprintf(out, out_size, "| %7d | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64
 			 " | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64 " |\n",
-			 idx0,
+			 0,
 			 stats.n_pkts[RTE_COLOR_GREEN],
 			 stats.n_pkts[RTE_COLOR_YELLOW],
 			 stats.n_pkts[RTE_COLOR_RED],
@@ -2353,7 +2549,13 @@ cmd_pipeline_meter_stats(char **tokens,
 			 stats.n_bytes[RTE_COLOR_RED]);
 		out_size -= strlen(out);
 		out += strlen(out);
+
+		return;
 	}
+
+	/* anything else. */
+	snprintf(out, out_size, "Invalid token %s\n.", tokens[5]);
+	return;
 }
 
 static const char cmd_pipeline_stats_help[] =
diff --git a/examples/pipeline/examples/meter.cli b/examples/pipeline/examples/meter.cli
index c1b88c882a..21582554b9 100644
--- a/examples/pipeline/examples/meter.cli
+++ b/examples/pipeline/examples/meter.cli
@@ -35,7 +35,7 @@ pipeline PIPELINE0 build lib /tmp/meter.so io ./examples/pipeline/examples/ethde
 ; The table entries can later be updated at run-time through the CLI commands.
 ;
 pipeline PIPELINE0 meter profile platinum add cir 46000000 pir 138000000 cbs 1000000 pbs 1000000
-pipeline PIPELINE0 meter meters from 0 to 15 set profile platinum
+pipeline PIPELINE0 meter meters set profile platinum index from 0 to 15
 
 ;
 ; Pipelines-to-threads mapping.
-- 
2.34.1