patch 'examples/vm_power_manager: fix vCPU number parsing' has been queued to stable release 24.11.9

luca.boccassi at gmail.com luca.boccassi at gmail.com
Tue Oct 27 12:50:21 CET 2026


Hi,

FYI, your patch has been queued to stable release 24.11.9

Note it hasn't been pushed to http://dpdk.org/browse/dpdk-stable yet.
It will be pushed if I get no objections before 10/29/26. So please
shout if anyone has objections.

Also note that after the patch there's a diff of the upstream commit vs the
patch applied to the branch. This will indicate if there was any rebasing
needed to apply to the stable branch. If there were code changes for rebasing
(ie: not only metadata diffs), please double check that the rebase was
correctly done.

Queued patches are on a temporary branch at:
https://github.com/bluca/dpdk-stable

This queued commit can be viewed at:
https://github.com/bluca/dpdk-stable/commit/35c6b08effe5c51f8d84a8832fb2ad8a311e086d

Thanks.

Luca Boccassi

---
>From 35c6b08effe5c51f8d84a8832fb2ad8a311e086d Mon Sep 17 00:00:00 2001
From: Stephen Hemminger <stephen at networkplumber.org>
Date: Fri, 28 Aug 2026 19:43:53 -0700
Subject: [PATCH] examples/vm_power_manager: fix vCPU number parsing

[ upstream commit efa95268ed48a41fe5a56195993ea050aab0b823 ]

The guest CLI parsed the vCPU argument of the query_cpu_freq and
query_cpu_caps commands with strtol(), storing the result in an
unsigned variable. Use strtoul() to match the type, and parse into
an unsigned long so the range check applies to the value strtoul()
returned rather than to an already truncated one.

The original code also accepted trailing garbage, so "3xyz"
and "3 4" parsed as 3; reject any unconsumed input.

Both commands duplicated this parsing along with the "all" handling.
Factor it into parse_vcpu_arg() and report the offending string and
the valid range instead of "Invalid parameter provided".

Fixes: 0e8f47491f09 ("examples/vm_power: add command to query CPU frequency")
Fixes: 07525d1a047a ("examples/vm_power: send capabilities request from guest")

Signed-off-by: Stephen Hemminger <stephen at networkplumber.org>
---
 .../guest_cli/vm_power_cli_guest.c            | 113 +++++++++---------
 1 file changed, 59 insertions(+), 54 deletions(-)

diff --git a/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c b/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c
index 3ba004ee742..b10ce9beea4 100644
--- a/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c
+++ b/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c
@@ -145,6 +145,47 @@ struct cmd_freq_list_result {
 	cmdline_fixed_string_t cpu_num;
 };
 
+/*
+ * Parse the vCPU argument of a query command, which is either "all" or a
+ * single vCPU number. A number indexes the per-vCPU arrays in the channel
+ * reply packets, so it must be below RTE_POWER_MAX_VCPU_PER_VM.
+ *
+ * Returns 1 for "all", 0 for a single vCPU, or -1 on error after printing
+ * the reason. On success *lcore_id is the lcore to communicate over, which
+ * for "all" is the first enabled lcore.
+ */
+static int
+parse_vcpu_arg(struct cmdline *cl, const char *str, unsigned int *lcore_id)
+{
+	unsigned long val;
+	char *ep;
+
+	if (!strcmp(str, "all")) {
+		/* Get first enabled lcore. */
+		*lcore_id = rte_get_next_lcore(-1, 0, 0);
+		if (*lcore_id == RTE_MAX_LCORE) {
+			cmdline_printf(cl, "Enabled core not found.\n");
+			return -1;
+		}
+		return 1;
+	}
+
+	errno = 0;
+	val = strtoul(str, &ep, 10);
+	if (errno != 0 || ep == str || *ep != '\0') {
+		cmdline_printf(cl, "Invalid vCPU number \"%s\".\n", str);
+		return -1;
+	}
+	if (val >= RTE_POWER_MAX_VCPU_PER_VM) {
+		cmdline_printf(cl, "vCPU number \"%s\" is out of range (max %u).\n",
+				str, RTE_POWER_MAX_VCPU_PER_VM - 1);
+		return -1;
+	}
+
+	*lcore_id = val;
+	return 0;
+}
+
 static int
 query_data(struct rte_power_channel_packet *pkt, unsigned int lcore_id)
 {
@@ -179,46 +220,28 @@ receive_freq_list(struct rte_power_channel_packet_freq_list *pkt_freq_list,
 
 static void
 cmd_query_freq_list_parsed(void *parsed_result,
-		__rte_unused struct cmdline *cl,
+		struct cmdline *cl,
 		__rte_unused void *data)
 {
 	struct cmd_freq_list_result *res = parsed_result;
 	unsigned int lcore_id;
 	struct rte_power_channel_packet_freq_list pkt_freq_list;
 	struct rte_power_channel_packet pkt;
-	bool query_list = false;
+	bool query_list;
 	int ret;
-	char *ep;
 
 	memset(&pkt, 0, sizeof(pkt));
 	memset(&pkt_freq_list, 0, sizeof(pkt_freq_list));
 
-	if (!strcmp(res->cpu_num, "all")) {
+	ret = parse_vcpu_arg(cl, res->cpu_num, &lcore_id);
+	if (ret < 0)
+		return;
 
-		/* Get first enabled lcore. */
-		lcore_id = rte_get_next_lcore(-1,
-				0,
-				0);
-		if (lcore_id == RTE_MAX_LCORE) {
-			cmdline_printf(cl, "Enabled core not found.\n");
-			return;
-		}
-
-		pkt.command = RTE_POWER_QUERY_FREQ_LIST;
-		strlcpy(pkt.vm_name, policy.vm_name, sizeof(pkt.vm_name));
-		query_list = true;
-	} else {
-		errno = 0;
-		lcore_id = (unsigned int)strtol(res->cpu_num, &ep, 10);
-		if (errno != 0 || lcore_id >= RTE_POWER_MAX_VCPU_PER_VM ||
-			ep == res->cpu_num) {
-			cmdline_printf(cl, "Invalid parameter provided.\n");
-			return;
-		}
-		pkt.command = RTE_POWER_QUERY_FREQ;
-		strlcpy(pkt.vm_name, policy.vm_name, sizeof(pkt.vm_name));
+	query_list = (ret == 1);
+	pkt.command = query_list ? RTE_POWER_QUERY_FREQ_LIST : RTE_POWER_QUERY_FREQ;
+	strlcpy(pkt.vm_name, policy.vm_name, sizeof(pkt.vm_name));
+	if (!query_list)
 		pkt.resource_id = lcore_id;
-	}
 
 	ret = query_data(&pkt, lcore_id);
 	if (ret < 0) {
@@ -289,46 +312,28 @@ receive_capabilities(struct rte_power_channel_packet_caps_list *pkt_caps_list,
 
 static void
 cmd_query_caps_list_parsed(void *parsed_result,
-		__rte_unused struct cmdline *cl,
+		struct cmdline *cl,
 		__rte_unused void *data)
 {
 	struct cmd_query_caps_result *res = parsed_result;
 	unsigned int lcore_id;
 	struct rte_power_channel_packet_caps_list pkt_caps_list;
 	struct rte_power_channel_packet pkt;
-	bool query_list = false;
+	bool query_list;
 	int ret;
-	char *ep;
 
 	memset(&pkt, 0, sizeof(pkt));
 	memset(&pkt_caps_list, 0, sizeof(pkt_caps_list));
 
-	if (!strcmp(res->cpu_num, "all")) {
+	ret = parse_vcpu_arg(cl, res->cpu_num, &lcore_id);
+	if (ret < 0)
+		return;
 
-		/* Get first enabled lcore. */
-		lcore_id = rte_get_next_lcore(-1,
-				0,
-				0);
-		if (lcore_id == RTE_MAX_LCORE) {
-			cmdline_printf(cl, "Enabled core not found.\n");
-			return;
-		}
-
-		pkt.command = RTE_POWER_QUERY_CAPS_LIST;
-		strlcpy(pkt.vm_name, policy.vm_name, sizeof(pkt.vm_name));
-		query_list = true;
-	} else {
-		errno = 0;
-		lcore_id = (unsigned int)strtol(res->cpu_num, &ep, 10);
-		if (errno != 0 || lcore_id >= RTE_POWER_MAX_VCPU_PER_VM ||
-			ep == res->cpu_num) {
-			cmdline_printf(cl, "Invalid parameter provided.\n");
-			return;
-		}
-		pkt.command = RTE_POWER_QUERY_CAPS;
-		strlcpy(pkt.vm_name, policy.vm_name, sizeof(pkt.vm_name));
+	query_list = (ret == 1);
+	pkt.command = query_list ? RTE_POWER_QUERY_CAPS_LIST : RTE_POWER_QUERY_CAPS;
+	strlcpy(pkt.vm_name, policy.vm_name, sizeof(pkt.vm_name));
+	if (!query_list)
 		pkt.resource_id = lcore_id;
-	}
 
 	ret = query_data(&pkt, lcore_id);
 	if (ret < 0) {
-- 
2.47.3

---
  Diff of the applied patch vs upstream commit (please double-check if non-empty:
---
--- -	2026-10-27 11:43:58.613424925 +0000
+++ 0127-examples-vm_power_manager-fix-vCPU-number-parsing.patch	2026-10-27 11:43:53.654063782 +0000
@@ -1 +1 @@
-From efa95268ed48a41fe5a56195993ea050aab0b823 Mon Sep 17 00:00:00 2001
+From 35c6b08effe5c51f8d84a8832fb2ad8a311e086d Mon Sep 17 00:00:00 2001
@@ -5,0 +6,2 @@
+[ upstream commit efa95268ed48a41fe5a56195993ea050aab0b823 ]
+
@@ -21 +22,0 @@
-Cc: stable at dpdk.org
@@ -29 +30 @@
-index cd0d87d1e7..f7ffda1381 100644
+index 3ba004ee742..b10ce9beea4 100644


More information about the stable mailing list