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 <[email protected]> --- 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

