examples/l3fwd-power: add ethdev power management

Add PMD power management feature support to l3fwd-power sample app.

Signed-off-by: Liang Ma <liang.j.ma@intel.com>
Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
Acked-by: David Hunt <david.hunt@intel.com>
This commit is contained in:
Liang Ma 2021-01-22 17:12:17 +00:00 committed by Thomas Monjalon
parent 682a645438
commit 26fe454ec0
2 changed files with 131 additions and 2 deletions

View File

@ -109,6 +109,8 @@ where,
* --telemetry: Telemetry mode.
* --pmd-mgmt: PMD power management mode.
See :doc:`l3_forward` for details.
The L3fwd-power example reuses the L3fwd command line options.
@ -456,3 +458,44 @@ reference cycles and accordingly busy rate is set to either 0% or
The new stats ``empty_poll`` , ``full_poll`` and ``busy_percent`` can be viewed by running the script
``/usertools/dpdk-telemetry-client.py`` and selecting the menu option ``Send for global Metrics``.
PMD power management Mode
-------------------------
The PMD power management mode support for ``l3fwd-power`` is a standalone mode.
In this mode, ``l3fwd-power`` does simple l3fwding
along with enabling the power saving scheme on specific port/queue/lcore.
Main purpose for this mode is to demonstrate
how to use the PMD power management API.
.. code-block:: console
./build/examples/dpdk-l3fwd-power -l 1-3 -- --pmd-mgmt -p 0x0f --config="(0,0,2),(0,1,3)"
PMD Power Management Mode
-------------------------
There is also a traffic-aware operating mode that,
instead of using explicit power management,
will use automatic PMD power management.
This mode is limited to one queue per core,
and has three available power management schemes:
``monitor``
This will use ``rte_power_monitor()`` function to enter
a power-optimized state (subject to platform support).
``pause``
This will use ``rte_power_pause()`` or ``rte_pause()``
to avoid busy looping when there is no traffic.
``scale``
This will use frequency scaling routines
available in the ``librte_power`` library.
See :doc:`Power Management<../prog_guide/power_man>` chapter
in the DPDK Programmer's Guide for more details on PMD power management.
.. code-block:: console
./<build_dir>/examples/dpdk-l3fwd-power -l 1-3 -- -p 0x0f --config="(0,0,2),(0,1,3)" --pmd-mgmt=scale

View File

@ -47,6 +47,7 @@
#include <rte_power_empty_poll.h>
#include <rte_metrics.h>
#include <rte_telemetry.h>
#include <rte_power_pmd_mgmt.h>
#include "perf_core.h"
#include "main.h"
@ -199,11 +200,14 @@ enum appmode {
APP_MODE_LEGACY,
APP_MODE_EMPTY_POLL,
APP_MODE_TELEMETRY,
APP_MODE_INTERRUPT
APP_MODE_INTERRUPT,
APP_MODE_PMD_MGMT
};
enum appmode app_mode;
static enum rte_power_pmd_mgmt_type pmgmt_type;
enum freq_scale_hint_t
{
FREQ_LOWER = -1,
@ -1611,7 +1615,9 @@ print_usage(const char *prgname)
" follow (training_flag, high_threshold, med_threshold)\n"
" --telemetry: enable telemetry mode, to update"
" empty polls, full polls, and core busyness to telemetry\n"
" --interrupt-only: enable interrupt-only mode\n",
" --interrupt-only: enable interrupt-only mode\n"
" --pmd-mgmt MODE: enable PMD power management mode. "
"Currently supported modes: monitor, pause, scale\n",
prgname);
}
@ -1701,6 +1707,32 @@ parse_config(const char *q_arg)
return 0;
}
static int
parse_pmd_mgmt_config(const char *name)
{
#define PMD_MGMT_MONITOR "monitor"
#define PMD_MGMT_PAUSE "pause"
#define PMD_MGMT_SCALE "scale"
if (strncmp(PMD_MGMT_MONITOR, name, sizeof(PMD_MGMT_MONITOR)) == 0) {
pmgmt_type = RTE_POWER_MGMT_TYPE_MONITOR;
return 0;
}
if (strncmp(PMD_MGMT_PAUSE, name, sizeof(PMD_MGMT_PAUSE)) == 0) {
pmgmt_type = RTE_POWER_MGMT_TYPE_PAUSE;
return 0;
}
if (strncmp(PMD_MGMT_SCALE, name, sizeof(PMD_MGMT_SCALE)) == 0) {
pmgmt_type = RTE_POWER_MGMT_TYPE_SCALE;
return 0;
}
/* unknown PMD power management mode */
return -1;
}
static int
parse_ep_config(const char *q_arg)
{
@ -1755,6 +1787,7 @@ parse_ep_config(const char *q_arg)
#define CMD_LINE_OPT_EMPTY_POLL "empty-poll"
#define CMD_LINE_OPT_INTERRUPT_ONLY "interrupt-only"
#define CMD_LINE_OPT_TELEMETRY "telemetry"
#define CMD_LINE_OPT_PMD_MGMT "pmd-mgmt"
/* Parse the argument given in the command line of the application */
static int
@ -1776,6 +1809,7 @@ parse_args(int argc, char **argv)
{CMD_LINE_OPT_LEGACY, 0, 0, 0},
{CMD_LINE_OPT_TELEMETRY, 0, 0, 0},
{CMD_LINE_OPT_INTERRUPT_ONLY, 0, 0, 0},
{CMD_LINE_OPT_PMD_MGMT, 1, 0, 0},
{NULL, 0, 0, 0}
};
@ -1886,6 +1920,21 @@ parse_args(int argc, char **argv)
printf("telemetry mode is enabled\n");
}
if (!strncmp(lgopts[option_index].name,
CMD_LINE_OPT_PMD_MGMT,
sizeof(CMD_LINE_OPT_PMD_MGMT))) {
if (app_mode != APP_MODE_DEFAULT) {
printf(" power mgmt mode is mutually exclusive with other modes\n");
return -1;
}
if (parse_pmd_mgmt_config(optarg) < 0) {
printf(" Invalid PMD power management mode: %s\n",
optarg);
return -1;
}
app_mode = APP_MODE_PMD_MGMT;
printf("PMD power mgmt mode is enabled\n");
}
if (!strncmp(lgopts[option_index].name,
CMD_LINE_OPT_INTERRUPT_ONLY,
sizeof(CMD_LINE_OPT_INTERRUPT_ONLY))) {
@ -2442,6 +2491,8 @@ mode_to_str(enum appmode mode)
return "telemetry";
case APP_MODE_INTERRUPT:
return "interrupt-only";
case APP_MODE_PMD_MGMT:
return "pmd mgmt";
default:
return "invalid";
}
@ -2671,6 +2722,13 @@ main(int argc, char **argv)
qconf = &lcore_conf[lcore_id];
printf("\nInitializing rx queues on lcore %u ... ", lcore_id );
fflush(stdout);
/* PMD power management mode can only do 1 queue per core */
if (app_mode == APP_MODE_PMD_MGMT && qconf->n_rx_queue > 1) {
rte_exit(EXIT_FAILURE,
"In PMD power management mode, only one queue per lcore is allowed\n");
}
/* init RX queues */
for(queue = 0; queue < qconf->n_rx_queue; ++queue) {
struct rte_eth_rxconf rxq_conf;
@ -2708,6 +2766,16 @@ main(int argc, char **argv)
rte_exit(EXIT_FAILURE,
"Fail to add ptype cb\n");
}
if (app_mode == APP_MODE_PMD_MGMT) {
ret = rte_power_ethdev_pmgmt_queue_enable(
lcore_id, portid, queueid,
pmgmt_type);
if (ret < 0)
rte_exit(EXIT_FAILURE,
"rte_power_ethdev_pmgmt_queue_enable: err=%d, port=%d\n",
ret, portid);
}
}
}
@ -2798,6 +2866,9 @@ main(int argc, char **argv)
SKIP_MAIN);
} else if (app_mode == APP_MODE_INTERRUPT) {
rte_eal_mp_remote_launch(main_intr_loop, NULL, CALL_MAIN);
} else if (app_mode == APP_MODE_PMD_MGMT) {
/* reuse telemetry loop for PMD power management mode */
rte_eal_mp_remote_launch(main_telemetry_loop, NULL, CALL_MAIN);
}
if (app_mode == APP_MODE_EMPTY_POLL || app_mode == APP_MODE_TELEMETRY)
@ -2808,6 +2879,21 @@ main(int argc, char **argv)
return -1;
}
if (app_mode == APP_MODE_PMD_MGMT) {
for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
if (rte_lcore_is_enabled(lcore_id) == 0)
continue;
qconf = &lcore_conf[lcore_id];
for (queue = 0; queue < qconf->n_rx_queue; ++queue) {
portid = qconf->rx_queue_list[queue].port_id;
queueid = qconf->rx_queue_list[queue].queue_id;
rte_power_ethdev_pmgmt_queue_disable(lcore_id,
portid, queueid);
}
}
}
RTE_ETH_FOREACH_DEV(portid)
{
if ((enabled_port_mask & (1 << portid)) == 0)