[RFC 1/2] app/testpmd: add option to set flow control mode
Stephen Hemminger
stephen at networkplumber.org
Sat Oct 17 21:48:54 CEST 2026
When doing benchmarking it is important to disable NIC
flow control. Testpmd can do this only from the interactive
command line, there was no option to do this from a script.
Add --flow-ctrl=none|rx|tx|full, applied each time a port
is started. Devices without flow control support are skipped.
Signed-off-by: Stephen Hemminger <stephen at networkplumber.org>
---
app/test-pmd/parameters.c | 18 +++++++++++++++++
app/test-pmd/testpmd.c | 28 +++++++++++++++++++++++++++
app/test-pmd/testpmd.h | 1 +
doc/guides/testpmd_app_ug/run_app.rst | 5 +++++
4 files changed, 52 insertions(+)
diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 833b14eda4..f031dd7445 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -207,6 +207,8 @@ enum {
TESTPMD_OPT_NO_LSC_INTERRUPT_NUM,
#define TESTPMD_OPT_NO_RMV_INTERRUPT "no-rmv-interrupt"
TESTPMD_OPT_NO_RMV_INTERRUPT_NUM,
+#define TESTPMD_OPT_FLOW_CTRL "flow-ctrl"
+ TESTPMD_OPT_FLOW_CTRL_NUM,
#define TESTPMD_OPT_PRINT_EVENT "print-event"
TESTPMD_OPT_PRINT_EVENT_NUM,
#define TESTPMD_OPT_MASK_EVENT "mask-event"
@@ -357,6 +359,7 @@ static const struct option long_options[] = {
NO_ARG(TESTPMD_OPT_DISABLE_DEVICE_START),
NO_ARG(TESTPMD_OPT_NO_LSC_INTERRUPT),
NO_ARG(TESTPMD_OPT_NO_RMV_INTERRUPT),
+ REQUIRED_ARG(TESTPMD_OPT_FLOW_CTRL),
REQUIRED_ARG(TESTPMD_OPT_PRINT_EVENT),
REQUIRED_ARG(TESTPMD_OPT_MASK_EVENT),
REQUIRED_ARG(TESTPMD_OPT_TX_OFFLOADS),
@@ -515,6 +518,8 @@ usage(char* progname)
printf(" --disable-device-start: do not automatically start port\n");
printf(" --no-lsc-interrupt: disable link status change interrupt.\n");
printf(" --no-rmv-interrupt: disable device removal interrupt.\n");
+ printf(" --flow-ctrl=none|rx|tx|full: set Ethernet flow control"
+ " mode when ports are started.\n");
#ifdef RTE_LIB_BITRATESTATS
printf(" --bitrate-stats=N: set the logical core N to perform "
"bit-rate calculation.\n");
@@ -1635,6 +1640,19 @@ launch_args_parse(int argc, char** argv)
case TESTPMD_OPT_NO_RMV_INTERRUPT_NUM:
rmv_interrupt = 0;
break;
+ case TESTPMD_OPT_FLOW_CTRL_NUM:
+ if (!strcmp(optarg, "none"))
+ flow_ctrl_mode = RTE_ETH_FC_NONE;
+ else if (!strcmp(optarg, "rx"))
+ flow_ctrl_mode = RTE_ETH_FC_RX_PAUSE;
+ else if (!strcmp(optarg, "tx"))
+ flow_ctrl_mode = RTE_ETH_FC_TX_PAUSE;
+ else if (!strcmp(optarg, "full"))
+ flow_ctrl_mode = RTE_ETH_FC_FULL;
+ else
+ rte_exit(EXIT_FAILURE,
+ "flow-ctrl must be none, rx, tx or full\n");
+ break;
case TESTPMD_OPT_FLOW_ISOLATE_ALL_NUM:
flow_isolate_all = 1;
break;
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index d6211a9a8a..e1766eec72 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -446,6 +446,12 @@ uint8_t lsc_interrupt = 1; /* enabled by default */
*/
uint8_t rmv_interrupt = 1; /* enabled by default */
+/*
+ * Ethernet flow control mode applied on port start.
+ * Negative means leave the device default.
+ */
+int flow_ctrl_mode = -1;
+
uint8_t hot_plug = 0; /**< hotplug disabled by default. */
/* After attach, port setup is called on event or by iterator */
@@ -2973,6 +2979,26 @@ update_bonding_port_dev_conf(portid_t bond_pid)
#endif
}
+static void
+port_flow_ctrl_apply(portid_t pi)
+{
+ struct rte_eth_fc_conf fc_conf;
+ int ret;
+
+ if (flow_ctrl_mode < 0 || !is_proc_primary())
+ return;
+
+ memset(&fc_conf, 0, sizeof(fc_conf));
+ ret = rte_eth_dev_flow_ctrl_get(pi, &fc_conf);
+ if (ret == 0) {
+ fc_conf.mode = flow_ctrl_mode;
+ ret = rte_eth_dev_flow_ctrl_set(pi, &fc_conf);
+ }
+ if (ret != 0 && ret != -ENOTSUP)
+ fprintf(stderr, "Port %u: failed to set flow control: %s\n",
+ pi, rte_strerror(-ret));
+}
+
int
start_port(portid_t pid)
{
@@ -3229,6 +3255,8 @@ start_port(portid_t pid)
fprintf(stderr, "Port %d can not be set into started\n",
pi);
+ port_flow_ctrl_apply(pi);
+
if (eth_macaddr_get_print_err(pi, &port->eth_addr) == 0)
printf("Port %d: " RTE_ETHER_ADDR_PRT_FMT "\n", pi,
RTE_ETHER_ADDR_BYTES(&port->eth_addr));
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 2ca4aaf086..6d4c3e8f84 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -541,6 +541,7 @@ extern uint8_t no_device_start; /**<set by "--disable-device-start" parameter */
extern volatile int test_done; /* stop packet forwarding when set to 1. */
extern uint8_t lsc_interrupt; /**< disabled by "--no-lsc-interrupt" parameter */
extern uint8_t rmv_interrupt; /**< disabled by "--no-rmv-interrupt" parameter */
+extern int flow_ctrl_mode; /**< set by "--flow-ctrl" parameter */
extern uint32_t event_print_mask;
/**< set by "--print-event xxxx" and "--mask-event xxxx parameters */
extern bool setup_on_probe_event; /**< disabled by port setup-on iterator */
diff --git a/doc/guides/testpmd_app_ug/run_app.rst b/doc/guides/testpmd_app_ug/run_app.rst
index bcfbf33f92..e678058b97 100644
--- a/doc/guides/testpmd_app_ug/run_app.rst
+++ b/doc/guides/testpmd_app_ug/run_app.rst
@@ -224,6 +224,11 @@ The command line options are:
Disable RSS (Receive Side Scaling).
+* ``--flow-ctrl=mode``
+
+ Set the Ethernet flow control mode of all ports each time they are started.
+ The possible values are ``none``, ``rx``, ``tx`` and ``full``.
+
* ``--port-topology=mode``
Set port topology, where mode is ``paired`` (the default), ``chained`` or ``loop``.
--
2.53.0
More information about the dev
mailing list