DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH 0/4] testpmd options parsing cleanup
@ 2024-03-08 14:48 David Marchand
  2024-03-08 14:48 ` [PATCH 1/4] app/testpmd: fix stats-period option check David Marchand
                   ` (4 more replies)
  0 siblings, 5 replies; 35+ messages in thread
From: David Marchand @ 2024-03-08 14:48 UTC (permalink / raw)
  To: dev

This is a cleanup I had in store for ages but never sent.
The idea is to reuse the conventions from EAL and examples when it
comes to using getopt API.

-- 
David Marchand

David Marchand (4):
  app/testpmd: fix stats-period option check
  app/testpmd: fix burst option parsing
  app/testpmd: check queue count for related options
  app/testpmd: enhance getopt_long usage

 app/test-pmd/parameters.c | 1926 +++++++++++++++++++++----------------
 1 file changed, 1083 insertions(+), 843 deletions(-)

-- 
2.44.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH 1/4] app/testpmd: fix stats-period option check
  2024-03-08 14:48 [PATCH 0/4] testpmd options parsing cleanup David Marchand
@ 2024-03-08 14:48 ` David Marchand
  2024-03-12 16:43   ` Ferruh Yigit
  2024-03-08 14:48 ` [PATCH 2/4] app/testpmd: fix burst option parsing David Marchand
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 35+ messages in thread
From: David Marchand @ 2024-03-08 14:48 UTC (permalink / raw)
  To: dev; +Cc: stable, Aman Singh, Yuying Zhang, Pablo de Lara, Jingjing Wu

Rather than silently ignore an invalid value, raise an error for
stats-period user input.

Fixes: cfea1f3048d1 ("app/testpmd: print statistics periodically")
Cc: stable@dpdk.org

Signed-off-by: David Marchand <david.marchand@redhat.com>
---
 app/test-pmd/parameters.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 11b0cce577..d715750bb8 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -776,7 +776,7 @@ launch_args_parse(int argc, char** argv)
 				n = strtoul(optarg, &end, 10);
 				if ((optarg[0] == '\0') || (end == NULL) ||
 						(*end != '\0'))
-					break;
+					rte_exit(EXIT_FAILURE, "Invalid stats-period value\n");
 
 				stats_period = n;
 				break;
-- 
2.44.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH 2/4] app/testpmd: fix burst option parsing
  2024-03-08 14:48 [PATCH 0/4] testpmd options parsing cleanup David Marchand
  2024-03-08 14:48 ` [PATCH 1/4] app/testpmd: fix stats-period option check David Marchand
@ 2024-03-08 14:48 ` David Marchand
  2024-03-12 16:47   ` Ferruh Yigit
  2024-03-08 14:48 ` [PATCH 3/4] app/testpmd: check queue count for related options David Marchand
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 35+ messages in thread
From: David Marchand @ 2024-03-08 14:48 UTC (permalink / raw)
  To: dev
  Cc: stable, Aman Singh, Yuying Zhang, Ivan Ilchenko,
	Andrew Rybchenko, Bernard Iremonger

rte_eth_dev_info_get() is not supposed to fail for a valid port_id, but
for the theoretical case when it would fail, raise an error rather than
skip subsequent options.

Fixes: 6f51deb903b2 ("app/testpmd: check status of getting ethdev info")
Cc: stable@dpdk.org

Signed-off-by: David Marchand <david.marchand@redhat.com>
---
 app/test-pmd/parameters.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index d715750bb8..8c21744009 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -1128,9 +1128,9 @@ launch_args_parse(int argc, char** argv)
 								0,
 								&dev_info);
 					if (ret != 0)
-						return;
-
-					rec_nb_pkts = dev_info
+						rec_nb_pkts = 0;
+					else
+						rec_nb_pkts = dev_info
 						.default_rxportconf.burst_size;
 
 					if (rec_nb_pkts == 0)
-- 
2.44.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH 3/4] app/testpmd: check queue count for related options
  2024-03-08 14:48 [PATCH 0/4] testpmd options parsing cleanup David Marchand
  2024-03-08 14:48 ` [PATCH 1/4] app/testpmd: fix stats-period option check David Marchand
  2024-03-08 14:48 ` [PATCH 2/4] app/testpmd: fix burst option parsing David Marchand
@ 2024-03-08 14:48 ` David Marchand
  2024-03-12 16:59   ` Ferruh Yigit
  2024-03-08 14:48 ` [PATCH 4/4] app/testpmd: enhance getopt_long usage David Marchand
  2024-03-14  9:17 ` [PATCH v2 0/6] testpmd options parsing cleanup David Marchand
  4 siblings, 1 reply; 35+ messages in thread
From: David Marchand @ 2024-03-08 14:48 UTC (permalink / raw)
  To: dev; +Cc: Aman Singh, Yuying Zhang

Checking the number of rxq/txq in the middle of option parsing is
confusing. Move the check where nb_rxq / nb_txq are modified.

Signed-off-by: David Marchand <david.marchand@redhat.com>
---
 app/test-pmd/parameters.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 8c21744009..271f0c995a 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -1063,6 +1063,8 @@ launch_args_parse(int argc, char** argv)
 					rte_exit(EXIT_FAILURE, "rxq %d invalid - must be"
 						  " >= 0 && <= %u\n", n,
 						  get_allowed_max_nb_rxq(&pid));
+				if (!nb_rxq && !nb_txq)
+					rte_exit(EXIT_FAILURE, "Either rx or tx queues should be non-zero\n");
 			}
 			if (!strcmp(lgopts[opt_idx].name, "txq")) {
 				n = atoi(optarg);
@@ -1072,6 +1074,8 @@ launch_args_parse(int argc, char** argv)
 					rte_exit(EXIT_FAILURE, "txq %d invalid - must be"
 						  " >= 0 && <= %u\n", n,
 						  get_allowed_max_nb_txq(&pid));
+				if (!nb_rxq && !nb_txq)
+					rte_exit(EXIT_FAILURE, "Either rx or tx queues should be non-zero\n");
 			}
 			if (!strcmp(lgopts[opt_idx].name, "hairpinq")) {
 				n = atoi(optarg);
@@ -1098,10 +1102,6 @@ launch_args_parse(int argc, char** argv)
 						  n + nb_rxq,
 						  get_allowed_max_nb_rxq(&pid));
 			}
-			if (!nb_rxq && !nb_txq) {
-				rte_exit(EXIT_FAILURE, "Either rx or tx queues should "
-						"be non-zero\n");
-			}
 			if (!strcmp(lgopts[opt_idx].name, "hairpin-mode")) {
 				char *end = NULL;
 				unsigned int n;
-- 
2.44.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH 4/4] app/testpmd: enhance getopt_long usage
  2024-03-08 14:48 [PATCH 0/4] testpmd options parsing cleanup David Marchand
                   ` (2 preceding siblings ...)
  2024-03-08 14:48 ` [PATCH 3/4] app/testpmd: check queue count for related options David Marchand
@ 2024-03-08 14:48 ` David Marchand
  2024-03-12 17:03   ` Ferruh Yigit
  2024-03-14  9:17 ` [PATCH v2 0/6] testpmd options parsing cleanup David Marchand
  4 siblings, 1 reply; 35+ messages in thread
From: David Marchand @ 2024-03-08 14:48 UTC (permalink / raw)
  To: dev; +Cc: Aman Singh, Yuying Zhang

This is a cleanup similar to previous ones in EAL and examples.
Instead of using strcmp for every long options while getopt_long already
did such parsing, rely on getopt_long return value.

Note for reviewers: this patch is best reviewed once applied locally and
displayed with git show -w.

Signed-off-by: David Marchand <david.marchand@redhat.com>
---
 app/test-pmd/parameters.c | 1928 +++++++++++++++++++++----------------
 1 file changed, 1084 insertions(+), 844 deletions(-)

diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 271f0c995a..58f43cb5a8 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -40,6 +40,346 @@
 
 #include "testpmd.h"
 
+enum {
+	/* long options mapped to a short option */
+#define TESTPMD_OPT_AUTO_START "auto-start"
+	TESTPMD_OPT_AUTO_START_NUM = 'a',
+#define TESTPMD_OPT_HELP "help"
+	TESTPMD_OPT_HELP_NUM = 'h',
+#define TESTPMD_OPT_INTERACTIVE "interactive"
+	TESTPMD_OPT_INTERACTIVE_NUM = 'i',
+
+	/* first long only option value must be >= 256 */
+	TESTPMD_OPT_LONG_MIN_NUM = 256,
+#define TESTPMD_OPT_CMDLINE_FILE "cmdline-file"
+	TESTPMD_OPT_CMDLINE_FILE_NUM,
+#define TESTPMD_OPT_ETH_PEERS_CONFIGFILE "eth-peers-configfile"
+	TESTPMD_OPT_ETH_PEERS_CONFIGFILE_NUM,
+#define TESTPMD_OPT_ETH_PEER "eth-peer"
+	TESTPMD_OPT_ETH_PEER_NUM,
+#define TESTPMD_OPT_TX_FIRST "tx-first"
+	TESTPMD_OPT_TX_FIRST_NUM,
+#define TESTPMD_OPT_STATS_PERIOD "stats-period"
+	TESTPMD_OPT_STATS_PERIOD_NUM,
+#define TESTPMD_OPT_DISPLAY_XSTATS "display-xstats"
+	TESTPMD_OPT_DISPLAY_XSTATS_NUM,
+#define TESTPMD_OPT_NB_CORES "nb-cores"
+	TESTPMD_OPT_NB_CORES_NUM,
+#define TESTPMD_OPT_NB_PORTS "nb-ports"
+	TESTPMD_OPT_NB_PORTS_NUM,
+#define TESTPMD_OPT_COREMASK "coremask"
+	TESTPMD_OPT_COREMASK_NUM,
+#define TESTPMD_OPT_PORTMASK "portmask"
+	TESTPMD_OPT_PORTMASK_NUM,
+#define TESTPMD_OPT_PORTLIST "portlist"
+	TESTPMD_OPT_PORTLIST_NUM,
+#define TESTPMD_OPT_NUMA "numa"
+	TESTPMD_OPT_NUMA_NUM,
+#define TESTPMD_OPT_NO_NUMA "no-numa"
+	TESTPMD_OPT_NO_NUMA_NUM,
+#define TESTPMD_OPT_MP_ANON "mp-anon"
+	TESTPMD_OPT_MP_ANON_NUM,
+#define TESTPMD_OPT_PORT_NUMA_CONFIG "port-numa-config"
+	TESTPMD_OPT_PORT_NUMA_CONFIG_NUM,
+#define TESTPMD_OPT_RING_NUMA_CONFIG "ring-numa-config"
+	TESTPMD_OPT_RING_NUMA_CONFIG_NUM,
+#define TESTPMD_OPT_SOCKET_NUM "socket-num"
+	TESTPMD_OPT_SOCKET_NUM_NUM,
+#define TESTPMD_OPT_MBUF_SIZE "mbuf-size"
+	TESTPMD_OPT_MBUF_SIZE_NUM,
+#define TESTPMD_OPT_TOTAL_NUM_MBUFS "total-num-mbufs"
+	TESTPMD_OPT_TOTAL_NUM_MBUFS_NUM,
+#define TESTPMD_OPT_MAX_PKT_LEN "max-pkt-len"
+	TESTPMD_OPT_MAX_PKT_LEN_NUM,
+#define TESTPMD_OPT_MAX_LRO_PKT_SIZE "max-lro-pkt-size"
+	TESTPMD_OPT_MAX_LRO_PKT_SIZE_NUM,
+#define TESTPMD_OPT_LATENCYSTATS "latencystats"
+	TESTPMD_OPT_LATENCYSTATS_NUM,
+#define TESTPMD_OPT_BITRATE_STATS "bitrate-stats"
+	TESTPMD_OPT_BITRATE_STATS_NUM,
+#define TESTPMD_OPT_DISABLE_CRC_STRIP "disable-crc-strip"
+	TESTPMD_OPT_DISABLE_CRC_STRIP_NUM,
+#define TESTPMD_OPT_ENABLE_LRO "enable-lro"
+	TESTPMD_OPT_ENABLE_LRO_NUM,
+#define TESTPMD_OPT_ENABLE_RX_CKSUM "enable-rx-cksum"
+	TESTPMD_OPT_ENABLE_RX_CKSUM_NUM,
+#define TESTPMD_OPT_ENABLE_RX_TIMESTAMP "enable-rx-timestamp"
+	TESTPMD_OPT_ENABLE_RX_TIMESTAMP_NUM,
+#define TESTPMD_OPT_ENABLE_SCATTER "enable-scatter"
+	TESTPMD_OPT_ENABLE_SCATTER_NUM,
+#define TESTPMD_OPT_ENABLE_HW_VLAN "enable-hw-vlan"
+	TESTPMD_OPT_ENABLE_HW_VLAN_NUM,
+#define TESTPMD_OPT_ENABLE_HW_VLAN_FILTER "enable-hw-vlan-filter"
+	TESTPMD_OPT_ENABLE_HW_VLAN_FILTER_NUM,
+#define TESTPMD_OPT_ENABLE_HW_VLAN_STRIP "enable-hw-vlan-strip"
+	TESTPMD_OPT_ENABLE_HW_VLAN_STRIP_NUM,
+#define TESTPMD_OPT_ENABLE_HW_VLAN_EXTEND "enable-hw-vlan-extend"
+	TESTPMD_OPT_ENABLE_HW_VLAN_EXTEND_NUM,
+#define TESTPMD_OPT_ENABLE_HW_QINQ_STRIP "enable-hw-qinq-strip"
+	TESTPMD_OPT_ENABLE_HW_QINQ_STRIP_NUM,
+#define TESTPMD_OPT_ENABLE_DROP_EN "enable-drop-en"
+	TESTPMD_OPT_ENABLE_DROP_EN_NUM,
+#define TESTPMD_OPT_DISABLE_RSS "disable-rss"
+	TESTPMD_OPT_DISABLE_RSS_NUM,
+#define TESTPMD_OPT_PORT_TOPOLOGY "port-topology"
+	TESTPMD_OPT_PORT_TOPOLOGY_NUM,
+#define TESTPMD_OPT_FORWARD_MODE "forward-mode"
+	TESTPMD_OPT_FORWARD_MODE_NUM,
+#define TESTPMD_OPT_RSS_IP "rss-ip"
+	TESTPMD_OPT_RSS_IP_NUM,
+#define TESTPMD_OPT_RSS_UDP "rss-udp"
+	TESTPMD_OPT_RSS_UDP_NUM,
+#define TESTPMD_OPT_RSS_LEVEL_OUTER "rss-level-outer"
+	TESTPMD_OPT_RSS_LEVEL_OUTER_NUM,
+#define TESTPMD_OPT_RSS_LEVEL_INNER "rss-level-inner"
+	TESTPMD_OPT_RSS_LEVEL_INNER_NUM,
+#define TESTPMD_OPT_RXQ "rxq"
+	TESTPMD_OPT_RXQ_NUM,
+#define TESTPMD_OPT_TXQ "txq"
+	TESTPMD_OPT_TXQ_NUM,
+#define TESTPMD_OPT_RXD "rxd"
+	TESTPMD_OPT_RXD_NUM,
+#define TESTPMD_OPT_TXD "txd"
+	TESTPMD_OPT_TXD_NUM,
+#define TESTPMD_OPT_HAIRPINQ "hairpinq"
+	TESTPMD_OPT_HAIRPINQ_NUM,
+#define TESTPMD_OPT_HAIRPIN_MODE "hairpin-mode"
+	TESTPMD_OPT_HAIRPIN_MODE_NUM,
+#define TESTPMD_OPT_BURST "burst"
+	TESTPMD_OPT_BURST_NUM,
+#define TESTPMD_OPT_FLOWGEN_CLONES "flowgen-clones"
+	TESTPMD_OPT_FLOWGEN_CLONES_NUM,
+#define TESTPMD_OPT_FLOWGEN_FLOWS "flowgen-flows"
+	TESTPMD_OPT_FLOWGEN_FLOWS_NUM,
+#define TESTPMD_OPT_MBCACHE "mbcache"
+	TESTPMD_OPT_MBCACHE_NUM,
+#define TESTPMD_OPT_TXPT "txpt"
+	TESTPMD_OPT_TXPT_NUM,
+#define TESTPMD_OPT_TXHT "txht"
+	TESTPMD_OPT_TXHT_NUM,
+#define TESTPMD_OPT_TXWT "txwt"
+	TESTPMD_OPT_TXWT_NUM,
+#define TESTPMD_OPT_TXFREET "txfreet"
+	TESTPMD_OPT_TXFREET_NUM,
+#define TESTPMD_OPT_TXRST "txrst"
+	TESTPMD_OPT_TXRST_NUM,
+#define TESTPMD_OPT_RXPT "rxpt"
+	TESTPMD_OPT_RXPT_NUM,
+#define TESTPMD_OPT_RXHT "rxht"
+	TESTPMD_OPT_RXHT_NUM,
+#define TESTPMD_OPT_RXWT "rxwt"
+	TESTPMD_OPT_RXWT_NUM,
+#define TESTPMD_OPT_RXFREET "rxfreet"
+	TESTPMD_OPT_RXFREET_NUM,
+#define TESTPMD_OPT_NO_FLUSH_RX "no-flush-rx"
+	TESTPMD_OPT_NO_FLUSH_RX_NUM,
+#define TESTPMD_OPT_FLOW_ISOLATE_ALL "flow-isolate-all"
+	TESTPMD_OPT_FLOW_ISOLATE_ALL_NUM,
+#define TESTPMD_OPT_DISABLE_FLOW_FLUSH "disable-flow-flush"
+	TESTPMD_OPT_DISABLE_FLOW_FLUSH_NUM,
+#define TESTPMD_OPT_RXOFFS "rxoffs"
+	TESTPMD_OPT_RXOFFS_NUM,
+#define TESTPMD_OPT_RXPKTS "rxpkts"
+	TESTPMD_OPT_RXPKTS_NUM,
+#define TESTPMD_OPT_RXHDRS "rxhdrs"
+	TESTPMD_OPT_RXHDRS_NUM,
+#define TESTPMD_OPT_TXPKTS "txpkts"
+	TESTPMD_OPT_TXPKTS_NUM,
+#define TESTPMD_OPT_MULTI_RX_MEMPOOL "multi-rx-mempool"
+	TESTPMD_OPT_MULTI_RX_MEMPOOL_NUM,
+#define TESTPMD_OPT_TXONLY_MULTI_FLOW "txonly-multi-flow"
+	TESTPMD_OPT_TXONLY_MULTI_FLOW_NUM,
+#define TESTPMD_OPT_RXQ_SHARE "rxq-share"
+	TESTPMD_OPT_RXQ_SHARE_NUM,
+#define TESTPMD_OPT_ETH_LINK_SPEED "eth-link-speed"
+	TESTPMD_OPT_ETH_LINK_SPEED_NUM,
+#define TESTPMD_OPT_DISABLE_LINK_CHECK "disable-link-check"
+	TESTPMD_OPT_DISABLE_LINK_CHECK_NUM,
+#define TESTPMD_OPT_DISABLE_DEVICE_START "disable-device-start"
+	TESTPMD_OPT_DISABLE_DEVICE_START_NUM,
+#define TESTPMD_OPT_NO_LSC_INTERRUPT "no-lsc-interrupt"
+	TESTPMD_OPT_NO_LSC_INTERRUPT_NUM,
+#define TESTPMD_OPT_NO_RMV_INTERRUPT "no-rmv-interrupt"
+	TESTPMD_OPT_NO_RMV_INTERRUPT_NUM,
+#define TESTPMD_OPT_PRINT_EVENT "print-event"
+	TESTPMD_OPT_PRINT_EVENT_NUM,
+#define TESTPMD_OPT_MASK_EVENT "mask-event"
+	TESTPMD_OPT_MASK_EVENT_NUM,
+#define TESTPMD_OPT_TX_OFFLOADS "tx-offloads"
+	TESTPMD_OPT_TX_OFFLOADS_NUM,
+#define TESTPMD_OPT_RX_OFFLOADS "rx-offloads"
+	TESTPMD_OPT_RX_OFFLOADS_NUM,
+#define TESTPMD_OPT_HOT_PLUG "hot-plug"
+	TESTPMD_OPT_HOT_PLUG_NUM,
+#define TESTPMD_OPT_VXLAN_GPE_PORT "vxlan-gpe-port"
+	TESTPMD_OPT_VXLAN_GPE_PORT_NUM,
+#define TESTPMD_OPT_GENEVE_PARSED_PORT "geneve-parsed-port"
+	TESTPMD_OPT_GENEVE_PARSED_PORT_NUM,
+#define TESTPMD_OPT_MLOCKALL "mlockall"
+	TESTPMD_OPT_MLOCKALL_NUM,
+#define TESTPMD_OPT_NO_MLOCKALL "no-mlockall"
+	TESTPMD_OPT_NO_MLOCKALL_NUM,
+#define TESTPMD_OPT_MP_ALLOC "mp-alloc"
+	TESTPMD_OPT_MP_ALLOC_NUM,
+#define TESTPMD_OPT_TX_IP "tx-ip"
+	TESTPMD_OPT_TX_IP_NUM,
+#define TESTPMD_OPT_TX_UDP "tx-udp"
+	TESTPMD_OPT_TX_UDP_NUM,
+#define TESTPMD_OPT_NOISY_TX_SW_BUFFER_SIZE "noisy-tx-sw-buffer-size"
+	TESTPMD_OPT_NOISY_TX_SW_BUFFER_SIZE_NUM,
+#define TESTPMD_OPT_NOISY_TX_SW_BUFFER_FLUSHTIME "noisy-tx-sw-buffer-flushtime"
+	TESTPMD_OPT_NOISY_TX_SW_BUFFER_FLUSHTIME_NUM,
+#define TESTPMD_OPT_NOISY_LKUP_MEMORY "noisy-lkup-memory"
+	TESTPMD_OPT_NOISY_LKUP_MEMORY_NUM,
+#define TESTPMD_OPT_NOISY_LKUP_NUM_WRITES "noisy-lkup-num-writes"
+	TESTPMD_OPT_NOISY_LKUP_NUM_WRITES_NUM,
+#define TESTPMD_OPT_NOISY_LKUP_NUM_READS "noisy-lkup-num-reads"
+	TESTPMD_OPT_NOISY_LKUP_NUM_READS_NUM,
+#define TESTPMD_OPT_NOISY_LKUP_NUM_READS_WRITES "noisy-lkup-num-reads-writes"
+	TESTPMD_OPT_NOISY_LKUP_NUM_READS_WRITES_NUM,
+#define TESTPMD_OPT_NOISY_FORWARD_MODE "noisy-forward-mode"
+	TESTPMD_OPT_NOISY_FORWARD_MODE_NUM,
+#define TESTPMD_OPT_NO_IOVA_CONTIG "no-iova-contig"
+	TESTPMD_OPT_NO_IOVA_CONTIG_NUM,
+#define TESTPMD_OPT_RX_MQ_MODE "rx-mq-mode"
+	TESTPMD_OPT_RX_MQ_MODE_NUM,
+#define TESTPMD_OPT_RECORD_CORE_CYCLES "record-core-cycles"
+	TESTPMD_OPT_RECORD_CORE_CYCLES_NUM,
+#define TESTPMD_OPT_RECORD_BURST_STATS "record-burst-stats"
+	TESTPMD_OPT_RECORD_BURST_STATS_NUM,
+#define TESTPMD_OPT_NUM_PROCS "num-procs"
+	TESTPMD_OPT_NUM_PROCS_NUM,
+#define TESTPMD_OPT_PROC_ID "proc-id"
+	TESTPMD_OPT_PROC_ID_NUM,
+
+	TESTPMD_OPT_LONG_MAX_NUM
+};
+
+static const char short_options[] = {
+	"a" /* auto-start */
+	"h" /* help */
+#ifdef RTE_LIB_CMDLINE
+	"i" /* interactive */
+#endif
+};
+
+static struct option long_options[] = {
+	{ TESTPMD_OPT_AUTO_START, 0, NULL, TESTPMD_OPT_AUTO_START_NUM },
+	{ TESTPMD_OPT_HELP, 0, NULL, TESTPMD_OPT_HELP_NUM },
+#ifdef RTE_LIB_CMDLINE
+	{ TESTPMD_OPT_INTERACTIVE, 0, NULL, TESTPMD_OPT_INTERACTIVE_NUM },
+	{ TESTPMD_OPT_CMDLINE_FILE, 1, NULL, TESTPMD_OPT_CMDLINE_FILE_NUM },
+	{ TESTPMD_OPT_ETH_PEERS_CONFIGFILE, 1, NULL, TESTPMD_OPT_ETH_PEERS_CONFIGFILE_NUM },
+	{ TESTPMD_OPT_ETH_PEER, 1, NULL, TESTPMD_OPT_ETH_PEER_NUM },
+#endif
+	{ TESTPMD_OPT_TX_FIRST, 0, NULL, TESTPMD_OPT_TX_FIRST_NUM },
+	{ TESTPMD_OPT_STATS_PERIOD, 1, NULL, TESTPMD_OPT_STATS_PERIOD_NUM },
+	{ TESTPMD_OPT_DISPLAY_XSTATS, 1, NULL, TESTPMD_OPT_DISPLAY_XSTATS_NUM },
+	{ TESTPMD_OPT_NB_CORES, 1, NULL, TESTPMD_OPT_NB_CORES_NUM },
+	{ TESTPMD_OPT_NB_PORTS, 1, NULL, TESTPMD_OPT_NB_PORTS_NUM },
+	{ TESTPMD_OPT_COREMASK, 1, NULL, TESTPMD_OPT_COREMASK_NUM },
+	{ TESTPMD_OPT_PORTMASK, 1, NULL, TESTPMD_OPT_PORTMASK_NUM },
+	{ TESTPMD_OPT_PORTLIST, 1, NULL, TESTPMD_OPT_PORTLIST_NUM },
+	{ TESTPMD_OPT_NUMA, 0, NULL, TESTPMD_OPT_NUMA_NUM },
+	{ TESTPMD_OPT_NO_NUMA, 0, NULL, TESTPMD_OPT_NO_NUMA_NUM },
+	{ TESTPMD_OPT_MP_ANON, 0, NULL, TESTPMD_OPT_MP_ANON_NUM }, /* deprecated */
+	{ TESTPMD_OPT_PORT_NUMA_CONFIG, 1, NULL, TESTPMD_OPT_PORT_NUMA_CONFIG_NUM },
+	{ TESTPMD_OPT_RING_NUMA_CONFIG, 1, NULL, TESTPMD_OPT_RING_NUMA_CONFIG_NUM },
+	{ TESTPMD_OPT_SOCKET_NUM, 1, NULL, TESTPMD_OPT_SOCKET_NUM_NUM },
+	{ TESTPMD_OPT_MBUF_SIZE, 1, NULL, TESTPMD_OPT_MBUF_SIZE_NUM },
+	{ TESTPMD_OPT_TOTAL_NUM_MBUFS, 1, NULL, TESTPMD_OPT_TOTAL_NUM_MBUFS_NUM },
+	{ TESTPMD_OPT_MAX_PKT_LEN, 1, NULL, TESTPMD_OPT_MAX_PKT_LEN_NUM },
+	{ TESTPMD_OPT_MAX_LRO_PKT_SIZE, 1, NULL, TESTPMD_OPT_MAX_LRO_PKT_SIZE_NUM },
+#ifdef RTE_LIB_LATENCYSTATS
+	{ TESTPMD_OPT_LATENCYSTATS, 1, NULL, TESTPMD_OPT_LATENCYSTATS_NUM },
+#endif
+#ifdef RTE_LIB_BITRATESTATS
+	{ TESTPMD_OPT_BITRATE_STATS, 1, NULL, TESTPMD_OPT_BITRATE_STATS_NUM },
+#endif
+	{ TESTPMD_OPT_DISABLE_CRC_STRIP, 0, NULL, TESTPMD_OPT_DISABLE_CRC_STRIP_NUM },
+	{ TESTPMD_OPT_ENABLE_LRO, 0, NULL, TESTPMD_OPT_ENABLE_LRO_NUM },
+	{ TESTPMD_OPT_ENABLE_RX_CKSUM, 0, NULL, TESTPMD_OPT_ENABLE_RX_CKSUM_NUM },
+	{ TESTPMD_OPT_ENABLE_RX_TIMESTAMP, 0, NULL, TESTPMD_OPT_ENABLE_RX_TIMESTAMP_NUM },
+	{ TESTPMD_OPT_ENABLE_SCATTER, 0, NULL, TESTPMD_OPT_ENABLE_SCATTER_NUM },
+	{ TESTPMD_OPT_ENABLE_HW_VLAN, 0, NULL, TESTPMD_OPT_ENABLE_HW_VLAN_NUM },
+	{ TESTPMD_OPT_ENABLE_HW_VLAN_FILTER, 0, NULL, TESTPMD_OPT_ENABLE_HW_VLAN_FILTER_NUM },
+	{ TESTPMD_OPT_ENABLE_HW_VLAN_STRIP, 0, NULL, TESTPMD_OPT_ENABLE_HW_VLAN_STRIP_NUM },
+	{ TESTPMD_OPT_ENABLE_HW_VLAN_EXTEND, 0, NULL, TESTPMD_OPT_ENABLE_HW_VLAN_EXTEND_NUM },
+	{ TESTPMD_OPT_ENABLE_HW_QINQ_STRIP, 0, NULL, TESTPMD_OPT_ENABLE_HW_QINQ_STRIP_NUM },
+	{ TESTPMD_OPT_ENABLE_DROP_EN, 0, NULL, TESTPMD_OPT_ENABLE_DROP_EN_NUM },
+	{ TESTPMD_OPT_DISABLE_RSS, 0, NULL, TESTPMD_OPT_DISABLE_RSS_NUM },
+	{ TESTPMD_OPT_PORT_TOPOLOGY, 1, NULL, TESTPMD_OPT_PORT_TOPOLOGY_NUM },
+	{ TESTPMD_OPT_FORWARD_MODE, 1, NULL, TESTPMD_OPT_FORWARD_MODE_NUM },
+	{ TESTPMD_OPT_RSS_IP, 0, NULL, TESTPMD_OPT_RSS_IP_NUM },
+	{ TESTPMD_OPT_RSS_UDP, 0, NULL, TESTPMD_OPT_RSS_UDP_NUM },
+	{ TESTPMD_OPT_RSS_LEVEL_OUTER, 0, NULL, TESTPMD_OPT_RSS_LEVEL_OUTER_NUM },
+	{ TESTPMD_OPT_RSS_LEVEL_INNER, 0, NULL, TESTPMD_OPT_RSS_LEVEL_INNER_NUM },
+	{ TESTPMD_OPT_RXQ, 1, NULL, TESTPMD_OPT_RXQ_NUM },
+	{ TESTPMD_OPT_TXQ, 1, NULL, TESTPMD_OPT_TXQ_NUM },
+	{ TESTPMD_OPT_RXD, 1, NULL, TESTPMD_OPT_RXD_NUM },
+	{ TESTPMD_OPT_TXD, 1, NULL, TESTPMD_OPT_TXD_NUM },
+	{ TESTPMD_OPT_HAIRPINQ, 1, NULL, TESTPMD_OPT_HAIRPINQ_NUM },
+	{ TESTPMD_OPT_HAIRPIN_MODE, 1, NULL, TESTPMD_OPT_HAIRPIN_MODE_NUM },
+	{ TESTPMD_OPT_BURST, 1, NULL, TESTPMD_OPT_BURST_NUM },
+	{ TESTPMD_OPT_FLOWGEN_CLONES, 1, NULL, TESTPMD_OPT_FLOWGEN_CLONES_NUM },
+	{ TESTPMD_OPT_FLOWGEN_FLOWS, 1, NULL, TESTPMD_OPT_FLOWGEN_FLOWS_NUM },
+	{ TESTPMD_OPT_MBCACHE, 1, NULL, TESTPMD_OPT_MBCACHE_NUM },
+	{ TESTPMD_OPT_TXPT, 1, NULL, TESTPMD_OPT_TXPT_NUM },
+	{ TESTPMD_OPT_TXHT, 1, NULL, TESTPMD_OPT_TXHT_NUM },
+	{ TESTPMD_OPT_TXWT, 1, NULL, TESTPMD_OPT_TXWT_NUM },
+	{ TESTPMD_OPT_TXFREET, 1, NULL, TESTPMD_OPT_TXFREET_NUM },
+	{ TESTPMD_OPT_TXRST, 1, NULL, TESTPMD_OPT_TXRST_NUM },
+	{ TESTPMD_OPT_RXPT, 1, NULL, TESTPMD_OPT_RXPT_NUM },
+	{ TESTPMD_OPT_RXHT, 1, NULL, TESTPMD_OPT_RXHT_NUM },
+	{ TESTPMD_OPT_RXWT, 1, NULL, TESTPMD_OPT_RXWT_NUM },
+	{ TESTPMD_OPT_RXFREET, 1, NULL, TESTPMD_OPT_RXFREET_NUM },
+	{ TESTPMD_OPT_NO_FLUSH_RX, 0, NULL, TESTPMD_OPT_NO_FLUSH_RX_NUM },
+	{ TESTPMD_OPT_FLOW_ISOLATE_ALL, 0, NULL, TESTPMD_OPT_FLOW_ISOLATE_ALL_NUM },
+	{ TESTPMD_OPT_DISABLE_FLOW_FLUSH, 0, NULL, TESTPMD_OPT_DISABLE_FLOW_FLUSH_NUM },
+	{ TESTPMD_OPT_RXOFFS, 1, NULL, TESTPMD_OPT_RXOFFS_NUM },
+	{ TESTPMD_OPT_RXPKTS, 1, NULL, TESTPMD_OPT_RXPKTS_NUM },
+	{ TESTPMD_OPT_RXHDRS, 1, NULL, TESTPMD_OPT_RXHDRS_NUM },
+	{ TESTPMD_OPT_TXPKTS, 1, NULL, TESTPMD_OPT_TXPKTS_NUM },
+	{ TESTPMD_OPT_MULTI_RX_MEMPOOL, 0, NULL, TESTPMD_OPT_MULTI_RX_MEMPOOL_NUM },
+	{ TESTPMD_OPT_TXONLY_MULTI_FLOW, 0, NULL, TESTPMD_OPT_TXONLY_MULTI_FLOW_NUM },
+	{ TESTPMD_OPT_RXQ_SHARE, 2, NULL, TESTPMD_OPT_RXQ_SHARE_NUM },
+	{ TESTPMD_OPT_ETH_LINK_SPEED, 1, NULL, TESTPMD_OPT_ETH_LINK_SPEED_NUM },
+	{ TESTPMD_OPT_DISABLE_LINK_CHECK, 0, NULL, TESTPMD_OPT_DISABLE_LINK_CHECK_NUM },
+	{ TESTPMD_OPT_DISABLE_DEVICE_START, 0, NULL, TESTPMD_OPT_DISABLE_DEVICE_START_NUM },
+	{ TESTPMD_OPT_NO_LSC_INTERRUPT, 0, NULL, TESTPMD_OPT_NO_LSC_INTERRUPT_NUM },
+	{ TESTPMD_OPT_NO_RMV_INTERRUPT, 0, NULL, TESTPMD_OPT_NO_RMV_INTERRUPT_NUM },
+	{ TESTPMD_OPT_PRINT_EVENT, 1, NULL, TESTPMD_OPT_PRINT_EVENT_NUM },
+	{ TESTPMD_OPT_MASK_EVENT, 1, NULL, TESTPMD_OPT_MASK_EVENT_NUM },
+	{ TESTPMD_OPT_TX_OFFLOADS, 1, NULL, TESTPMD_OPT_TX_OFFLOADS_NUM },
+	{ TESTPMD_OPT_RX_OFFLOADS, 1, NULL, TESTPMD_OPT_RX_OFFLOADS_NUM },
+	{ TESTPMD_OPT_HOT_PLUG, 0, NULL, TESTPMD_OPT_HOT_PLUG_NUM },
+	{ TESTPMD_OPT_VXLAN_GPE_PORT, 1, NULL, TESTPMD_OPT_VXLAN_GPE_PORT_NUM },
+	{ TESTPMD_OPT_GENEVE_PARSED_PORT, 1, NULL, TESTPMD_OPT_GENEVE_PARSED_PORT_NUM },
+#ifndef RTE_EXEC_ENV_WINDOWS
+	{ TESTPMD_OPT_MLOCKALL, 0, NULL, TESTPMD_OPT_MLOCKALL_NUM },
+	{ TESTPMD_OPT_NO_MLOCKALL, 0, NULL, TESTPMD_OPT_NO_MLOCKALL_NUM },
+#endif
+	{ TESTPMD_OPT_MP_ALLOC, 1, NULL, TESTPMD_OPT_MP_ALLOC_NUM },
+	{ TESTPMD_OPT_TX_IP, 1, NULL, TESTPMD_OPT_TX_IP_NUM },
+	{ TESTPMD_OPT_TX_UDP, 1, NULL, TESTPMD_OPT_TX_UDP_NUM },
+	{ TESTPMD_OPT_NOISY_TX_SW_BUFFER_SIZE, 1, NULL, TESTPMD_OPT_NOISY_TX_SW_BUFFER_SIZE_NUM },
+	{ TESTPMD_OPT_NOISY_TX_SW_BUFFER_FLUSHTIME, 1, NULL,
+		TESTPMD_OPT_NOISY_TX_SW_BUFFER_FLUSHTIME_NUM },
+	{ TESTPMD_OPT_NOISY_LKUP_MEMORY, 1, NULL, TESTPMD_OPT_NOISY_LKUP_MEMORY_NUM },
+	{ TESTPMD_OPT_NOISY_LKUP_NUM_WRITES, 1, NULL, TESTPMD_OPT_NOISY_LKUP_NUM_WRITES_NUM },
+	{ TESTPMD_OPT_NOISY_LKUP_NUM_READS, 1, NULL, TESTPMD_OPT_NOISY_LKUP_NUM_READS_NUM },
+	{ TESTPMD_OPT_NOISY_LKUP_NUM_READS_WRITES, 1, NULL,
+		TESTPMD_OPT_NOISY_LKUP_NUM_READS_WRITES_NUM },
+	{ TESTPMD_OPT_NOISY_FORWARD_MODE, 1, NULL, TESTPMD_OPT_NOISY_FORWARD_MODE_NUM },
+	{ TESTPMD_OPT_NO_IOVA_CONTIG, 0, NULL, TESTPMD_OPT_NO_IOVA_CONTIG_NUM },
+	{ TESTPMD_OPT_RX_MQ_MODE, 1, NULL, TESTPMD_OPT_RX_MQ_MODE_NUM },
+	{ TESTPMD_OPT_RECORD_CORE_CYCLES, 0, NULL, TESTPMD_OPT_RECORD_CORE_CYCLES_NUM },
+	{ TESTPMD_OPT_RECORD_BURST_STATS, 0, NULL, TESTPMD_OPT_RECORD_BURST_STATS_NUM },
+	{ TESTPMD_OPT_NUM_PROCS, 1, NULL, TESTPMD_OPT_NUM_PROCS_NUM },
+	{ TESTPMD_OPT_PROC_ID, 1, NULL, TESTPMD_OPT_PROC_ID_NUM },
+	{ 0, 0, NULL, 0 }
+};
+
 static void
 usage(char* progname)
 {
@@ -593,9 +933,6 @@ parse_link_speed(int n)
 void
 launch_args_parse(int argc, char** argv)
 {
-#define PARAM_PROC_ID "proc-id"
-#define PARAM_NUM_PROCS "num-procs"
-
 	int n, opt;
 	char **argvopt;
 	int opt_idx;
@@ -608,130 +945,10 @@ launch_args_parse(int argc, char** argv)
 	uint16_t rec_nb_pkts;
 	int ret;
 
-	static struct option lgopts[] = {
-		{ "help",			0, 0, 0 },
-#ifdef RTE_LIB_CMDLINE
-		{ "interactive",		0, 0, 0 },
-		{ "cmdline-file",		1, 0, 0 },
-		{ "auto-start",			0, 0, 0 },
-		{ "eth-peers-configfile",	1, 0, 0 },
-		{ "eth-peer",			1, 0, 0 },
-#endif
-		{ "tx-first",			0, 0, 0 },
-		{ "stats-period",		1, 0, 0 },
-		{ "display-xstats",		1, 0, 0 },
-		{ "nb-cores",			1, 0, 0 },
-		{ "nb-ports",			1, 0, 0 },
-		{ "coremask",			1, 0, 0 },
-		{ "portmask",			1, 0, 0 },
-		{ "portlist",			1, 0, 0 },
-		{ "numa",			0, 0, 0 },
-		{ "no-numa",			0, 0, 0 },
-		{ "mp-anon",			0, 0, 0 }, /* deprecated */
-		{ "port-numa-config",           1, 0, 0 },
-		{ "ring-numa-config",           1, 0, 0 },
-		{ "socket-num",			1, 0, 0 },
-		{ "mbuf-size",			1, 0, 0 },
-		{ "total-num-mbufs",		1, 0, 0 },
-		{ "max-pkt-len",		1, 0, 0 },
-		{ "max-lro-pkt-size",		1, 0, 0 },
-#ifdef RTE_LIB_LATENCYSTATS
-		{ "latencystats",               1, 0, 0 },
-#endif
-#ifdef RTE_LIB_BITRATESTATS
-		{ "bitrate-stats",              1, 0, 0 },
-#endif
-		{ "disable-crc-strip",          0, 0, 0 },
-		{ "enable-lro",                 0, 0, 0 },
-		{ "enable-rx-cksum",            0, 0, 0 },
-		{ "enable-rx-timestamp",        0, 0, 0 },
-		{ "enable-scatter",             0, 0, 0 },
-		{ "enable-hw-vlan",             0, 0, 0 },
-		{ "enable-hw-vlan-filter",      0, 0, 0 },
-		{ "enable-hw-vlan-strip",       0, 0, 0 },
-		{ "enable-hw-vlan-extend",      0, 0, 0 },
-		{ "enable-hw-qinq-strip",       0, 0, 0 },
-		{ "enable-drop-en",            0, 0, 0 },
-		{ "disable-rss",                0, 0, 0 },
-		{ "port-topology",              1, 0, 0 },
-		{ "forward-mode",               1, 0, 0 },
-		{ "rss-ip",			0, 0, 0 },
-		{ "rss-udp",			0, 0, 0 },
-		{ "rss-level-outer",		0, 0, 0 },
-		{ "rss-level-inner",		0, 0, 0 },
-		{ "rxq",			1, 0, 0 },
-		{ "txq",			1, 0, 0 },
-		{ "rxd",			1, 0, 0 },
-		{ "txd",			1, 0, 0 },
-		{ "hairpinq",			1, 0, 0 },
-		{ "hairpin-mode",		1, 0, 0 },
-		{ "burst",			1, 0, 0 },
-		{ "flowgen-clones",		1, 0, 0 },
-		{ "flowgen-flows",		1, 0, 0 },
-		{ "mbcache",			1, 0, 0 },
-		{ "txpt",			1, 0, 0 },
-		{ "txht",			1, 0, 0 },
-		{ "txwt",			1, 0, 0 },
-		{ "txfreet",			1, 0, 0 },
-		{ "txrst",			1, 0, 0 },
-		{ "rxpt",			1, 0, 0 },
-		{ "rxht",			1, 0, 0 },
-		{ "rxwt",			1, 0, 0 },
-		{ "rxfreet",                    1, 0, 0 },
-		{ "no-flush-rx",	0, 0, 0 },
-		{ "flow-isolate-all",	        0, 0, 0 },
-		{ "disable-flow-flush",         0, 0, 0 },
-		{ "rxoffs",			1, 0, 0 },
-		{ "rxpkts",			1, 0, 0 },
-		{ "rxhdrs",			1, 0, 0 },
-		{ "txpkts",			1, 0, 0 },
-		{ "multi-rx-mempool",           0, 0, 0 },
-		{ "txonly-multi-flow",		0, 0, 0 },
-		{ "rxq-share",			2, 0, 0 },
-		{ "eth-link-speed",		1, 0, 0 },
-		{ "disable-link-check",		0, 0, 0 },
-		{ "disable-device-start",	0, 0, 0 },
-		{ "no-lsc-interrupt",		0, 0, 0 },
-		{ "no-rmv-interrupt",		0, 0, 0 },
-		{ "print-event",		1, 0, 0 },
-		{ "mask-event",			1, 0, 0 },
-		{ "tx-offloads",		1, 0, 0 },
-		{ "rx-offloads",		1, 0, 0 },
-		{ "hot-plug",			0, 0, 0 },
-		{ "vxlan-gpe-port",		1, 0, 0 },
-		{ "geneve-parsed-port",		1, 0, 0 },
-#ifndef RTE_EXEC_ENV_WINDOWS
-		{ "mlockall",			0, 0, 0 },
-		{ "no-mlockall",		0, 0, 0 },
-#endif
-		{ "mp-alloc",			1, 0, 0 },
-		{ "tx-ip",			1, 0, 0 },
-		{ "tx-udp",			1, 0, 0 },
-		{ "noisy-forward-mode",		1, 0, 0 },
-		{ "noisy-tx-sw-buffer-size",	1, 0, 0 },
-		{ "noisy-tx-sw-buffer-flushtime", 1, 0, 0 },
-		{ "noisy-lkup-memory",		1, 0, 0 },
-		{ "noisy-lkup-num-writes",	1, 0, 0 },
-		{ "noisy-lkup-num-reads",	1, 0, 0 },
-		{ "noisy-lkup-num-reads-writes", 1, 0, 0 },
-		{ "no-iova-contig",             0, 0, 0 },
-		{ "rx-mq-mode",                 1, 0, 0 },
-		{ "record-core-cycles",         0, 0, 0 },
-		{ "record-burst-stats",         0, 0, 0 },
-		{ PARAM_NUM_PROCS,              1, 0, 0 },
-		{ PARAM_PROC_ID,                1, 0, 0 },
-		{ 0, 0, 0, 0 },
-	};
-
 	argvopt = argv;
 
-#ifdef RTE_LIB_CMDLINE
-#define SHORTOPTS "i"
-#else
-#define SHORTOPTS ""
-#endif
-	while ((opt = getopt_long(argc, argvopt, SHORTOPTS "ah",
-				 lgopts, &opt_idx)) != EOF) {
+	while ((opt = getopt_long(argc, argvopt, short_options, long_options,
+			&opt_idx)) != EOF) {
 		switch (opt) {
 #ifdef RTE_LIB_CMDLINE
 		case 'i':
@@ -743,755 +960,778 @@ launch_args_parse(int argc, char** argv)
 			printf("Auto-start selected\n");
 			auto_start = 1;
 			break;
-
-		case 0: /*long options */
-			if (!strcmp(lgopts[opt_idx].name, "help")) {
-				usage(argv[0]);
-				exit(EXIT_SUCCESS);
-			}
+		case 'h':
+			usage(argv[0]);
+			exit(EXIT_SUCCESS);
+			break;
 #ifdef RTE_LIB_CMDLINE
-			if (!strcmp(lgopts[opt_idx].name, "interactive")) {
-				printf("Interactive-mode selected\n");
-				interactive = 1;
-			}
-			if (!strcmp(lgopts[opt_idx].name, "cmdline-file")) {
-				printf("CLI commands to be read from %s\n",
-				       optarg);
-				strlcpy(cmdline_filename, optarg,
-					sizeof(cmdline_filename));
-			}
-			if (!strcmp(lgopts[opt_idx].name, "auto-start")) {
-				printf("Auto-start selected\n");
-				auto_start = 1;
-			}
-			if (!strcmp(lgopts[opt_idx].name, "tx-first")) {
-				printf("Ports to start sending a burst of "
-						"packets first\n");
-				tx_first = 1;
-			}
-			if (!strcmp(lgopts[opt_idx].name, "stats-period")) {
-				char *end = NULL;
-				unsigned int n;
-
-				n = strtoul(optarg, &end, 10);
-				if ((optarg[0] == '\0') || (end == NULL) ||
-						(*end != '\0'))
-					rte_exit(EXIT_FAILURE, "Invalid stats-period value\n");
+		case TESTPMD_OPT_CMDLINE_FILE_NUM:
+			printf("CLI commands to be read from %s\n",
+				optarg);
+			strlcpy(cmdline_filename, optarg,
+				sizeof(cmdline_filename));
+			break;
+		case TESTPMD_OPT_TX_FIRST_NUM:
+			printf("Ports to start sending a burst of "
+				"packets first\n");
+			tx_first = 1;
+			break;
+		case TESTPMD_OPT_STATS_PERIOD_NUM: {
+			char *end = NULL;
+			unsigned int n;
 
-				stats_period = n;
-				break;
-			}
-			if (!strcmp(lgopts[opt_idx].name, "display-xstats")) {
-				char rc;
+			n = strtoul(optarg, &end, 10);
+			if ((optarg[0] == '\0') || (end == NULL) ||
+					(*end != '\0'))
+				rte_exit(EXIT_FAILURE, "Invalid stats-period value\n");
 
-				rc = parse_xstats_list(optarg, &xstats_display,
-						       &xstats_display_num);
-				if (rc != 0)
-					rte_exit(EXIT_FAILURE,
-						 "Failed to parse display-xstats argument: %d\n",
-						 rc);
-			}
-			if (!strcmp(lgopts[opt_idx].name,
-				    "eth-peers-configfile")) {
-				if (init_peer_eth_addrs(optarg) != 0)
-					rte_exit(EXIT_FAILURE,
-						 "Cannot open logfile\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "eth-peer")) {
-				char *port_end;
-
-				errno = 0;
-				n = strtoul(optarg, &port_end, 10);
-				if (errno != 0 || port_end == optarg || *port_end++ != ',')
-					rte_exit(EXIT_FAILURE,
-						 "Invalid eth-peer: %s", optarg);
-				if (n >= RTE_MAX_ETHPORTS)
-					rte_exit(EXIT_FAILURE,
-						 "eth-peer: port %d >= RTE_MAX_ETHPORTS(%d)\n",
-						 n, RTE_MAX_ETHPORTS);
+			stats_period = n;
+			break;
+		}
+		case TESTPMD_OPT_DISPLAY_XSTATS_NUM: {
+			char rc;
+
+			rc = parse_xstats_list(optarg, &xstats_display,
+				&xstats_display_num);
+			if (rc != 0)
+				rte_exit(EXIT_FAILURE,
+					"Failed to parse display-xstats argument: %d\n",
+					rc);
+			break;
+		}
+		case TESTPMD_OPT_ETH_PEERS_CONFIGFILE_NUM:
+			if (init_peer_eth_addrs(optarg) != 0)
+				rte_exit(EXIT_FAILURE,
+					"Cannot open logfile\n");
+			break;
+		case TESTPMD_OPT_ETH_PEER_NUM: {
+			char *port_end;
 
-				if (rte_ether_unformat_addr(port_end,
-						&peer_eth_addrs[n]) < 0)
-					rte_exit(EXIT_FAILURE,
-						 "Invalid ethernet address: %s\n",
-						 port_end);
-				nb_peer_eth_addrs++;
-			}
+			errno = 0;
+			n = strtoul(optarg, &port_end, 10);
+			if (errno != 0 || port_end == optarg || *port_end++ != ',')
+				rte_exit(EXIT_FAILURE,
+					"Invalid eth-peer: %s", optarg);
+			if (n >= RTE_MAX_ETHPORTS)
+				rte_exit(EXIT_FAILURE,
+					"eth-peer: port %d >= RTE_MAX_ETHPORTS(%d)\n",
+					n, RTE_MAX_ETHPORTS);
+
+			if (rte_ether_unformat_addr(port_end,
+					&peer_eth_addrs[n]) < 0)
+				rte_exit(EXIT_FAILURE,
+					"Invalid ethernet address: %s\n",
+					port_end);
+			nb_peer_eth_addrs++;
+			break;
+		}
 #endif
-			if (!strcmp(lgopts[opt_idx].name, "tx-ip")) {
-				struct in_addr in;
-				char *end;
-
-				end = strchr(optarg, ',');
-				if (end == optarg || !end)
-					rte_exit(EXIT_FAILURE,
-						 "Invalid tx-ip: %s", optarg);
-
-				*end++ = 0;
-				if (inet_pton(AF_INET, optarg, &in) == 0)
-					rte_exit(EXIT_FAILURE,
-						 "Invalid source IP address: %s\n",
-						 optarg);
-				tx_ip_src_addr = rte_be_to_cpu_32(in.s_addr);
-
-				if (inet_pton(AF_INET, end, &in) == 0)
-					rte_exit(EXIT_FAILURE,
-						 "Invalid destination IP address: %s\n",
-						 optarg);
-				tx_ip_dst_addr = rte_be_to_cpu_32(in.s_addr);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "tx-udp")) {
-				char *end = NULL;
-
-				errno = 0;
-				n = strtoul(optarg, &end, 10);
-				if (errno != 0 || end == optarg ||
-				    n > UINT16_MAX ||
-				    !(*end == '\0' || *end == ','))
-					rte_exit(EXIT_FAILURE,
-						 "Invalid UDP port: %s\n",
-						 optarg);
-				tx_udp_src_port = n;
-				if (*end == ',') {
-					char *dst = end + 1;
-
-					n = strtoul(dst, &end, 10);
-					if (errno != 0 || end == dst ||
-					    n > UINT16_MAX || *end)
-						rte_exit(EXIT_FAILURE,
-							 "Invalid destination UDP port: %s\n",
-							 dst);
-					tx_udp_dst_port = n;
-				} else {
-					tx_udp_dst_port = n;
-				}
+		case TESTPMD_OPT_TX_IP_NUM: {
+			struct in_addr in;
+			char *end;
+
+			end = strchr(optarg, ',');
+			if (end == optarg || !end)
+				rte_exit(EXIT_FAILURE,
+					"Invalid tx-ip: %s", optarg);
+
+			*end++ = 0;
+			if (inet_pton(AF_INET, optarg, &in) == 0)
+				rte_exit(EXIT_FAILURE,
+					"Invalid source IP address: %s\n",
+					optarg);
+			tx_ip_src_addr = rte_be_to_cpu_32(in.s_addr);
+
+			if (inet_pton(AF_INET, end, &in) == 0)
+				rte_exit(EXIT_FAILURE,
+					"Invalid destination IP address: %s\n",
+					optarg);
+			tx_ip_dst_addr = rte_be_to_cpu_32(in.s_addr);
+			break;
+		}
+		case TESTPMD_OPT_TX_UDP_NUM: {
+			char *end = NULL;
 
-			}
-			if (!strcmp(lgopts[opt_idx].name, "nb-ports")) {
-				n = atoi(optarg);
-				if (n > 0 && n <= nb_ports)
-					nb_fwd_ports = n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "Invalid port %d\n", n);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "nb-cores")) {
-				n = atoi(optarg);
-				if (n > 0 && n <= nb_lcores)
-					nb_fwd_lcores = (uint8_t) n;
-				else
+			errno = 0;
+			n = strtoul(optarg, &end, 10);
+			if (errno != 0 || end == optarg ||
+					n > UINT16_MAX ||
+					!(*end == '\0' || *end == ','))
+				rte_exit(EXIT_FAILURE,
+					"Invalid UDP port: %s\n",
+					optarg);
+			tx_udp_src_port = n;
+			if (*end == ',') {
+				char *dst = end + 1;
+
+				n = strtoul(dst, &end, 10);
+				if (errno != 0 || end == dst ||
+						n > UINT16_MAX || *end)
 					rte_exit(EXIT_FAILURE,
-						 "nb-cores should be > 0 and <= %d\n",
-						 nb_lcores);
+						"Invalid destination UDP port: %s\n",
+						dst);
+				tx_udp_dst_port = n;
+			} else {
+				tx_udp_dst_port = n;
 			}
-			if (!strcmp(lgopts[opt_idx].name, "coremask"))
-				parse_fwd_coremask(optarg);
-			if (!strcmp(lgopts[opt_idx].name, "portmask"))
-				parse_fwd_portmask(optarg);
-			if (!strcmp(lgopts[opt_idx].name, "portlist"))
-				parse_fwd_portlist(optarg);
-			if (!strcmp(lgopts[opt_idx].name, "no-numa"))
-				numa_support = 0;
-			if (!strcmp(lgopts[opt_idx].name, "numa"))
-				numa_support = 1;
-			if (!strcmp(lgopts[opt_idx].name, "mp-anon")) {
+			break;
+		}
+		case TESTPMD_OPT_NB_PORTS_NUM:
+			n = atoi(optarg);
+			if (n > 0 && n <= nb_ports)
+				nb_fwd_ports = n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"Invalid port %d\n", n);
+			break;
+		case TESTPMD_OPT_NB_CORES_NUM:
+			n = atoi(optarg);
+			if (n > 0 && n <= nb_lcores)
+				nb_fwd_lcores = (uint8_t) n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"nb-cores should be > 0 and <= %d\n",
+					nb_lcores);
+			break;
+		case TESTPMD_OPT_COREMASK_NUM:
+			parse_fwd_coremask(optarg);
+			break;
+		case TESTPMD_OPT_PORTMASK_NUM:
+			parse_fwd_portmask(optarg);
+			break;
+		case TESTPMD_OPT_PORTLIST_NUM:
+			parse_fwd_portlist(optarg);
+			break;
+		case TESTPMD_OPT_NO_NUMA_NUM:
+			numa_support = 0;
+			break;
+		case TESTPMD_OPT_NUMA_NUM:
+			numa_support = 1;
+			break;
+		case TESTPMD_OPT_MP_ANON_NUM:
+			mp_alloc_type = MP_ALLOC_ANON;
+			break;
+		case TESTPMD_OPT_MP_ALLOC_NUM:
+			if (!strcmp(optarg, "native"))
+				mp_alloc_type = MP_ALLOC_NATIVE;
+			else if (!strcmp(optarg, "anon"))
 				mp_alloc_type = MP_ALLOC_ANON;
+			else if (!strcmp(optarg, "xmem"))
+				mp_alloc_type = MP_ALLOC_XMEM;
+			else if (!strcmp(optarg, "xmemhuge"))
+				mp_alloc_type = MP_ALLOC_XMEM_HUGE;
+			else if (!strcmp(optarg, "xbuf"))
+				mp_alloc_type = MP_ALLOC_XBUF;
+			else
+				rte_exit(EXIT_FAILURE,
+					"mp-alloc %s invalid - must be: "
+					"native, anon, xmem or xmemhuge\n",
+					optarg);
+			break;
+		case TESTPMD_OPT_PORT_NUMA_CONFIG_NUM:
+			if (parse_portnuma_config(optarg))
+				rte_exit(EXIT_FAILURE,
+					"invalid port-numa configuration\n");
+			break;
+		case TESTPMD_OPT_RING_NUMA_CONFIG_NUM:
+			if (parse_ringnuma_config(optarg))
+				rte_exit(EXIT_FAILURE,
+					"invalid ring-numa configuration\n");
+			break;
+		case TESTPMD_OPT_SOCKET_NUM_NUM:
+			n = atoi(optarg);
+			if (!new_socket_id((uint8_t)n)) {
+				socket_num = (uint8_t)n;
+			} else {
+				print_invalid_socket_id_error();
+				rte_exit(EXIT_FAILURE,
+					"Invalid socket id");
 			}
-			if (!strcmp(lgopts[opt_idx].name, "mp-alloc")) {
-				if (!strcmp(optarg, "native"))
-					mp_alloc_type = MP_ALLOC_NATIVE;
-				else if (!strcmp(optarg, "anon"))
-					mp_alloc_type = MP_ALLOC_ANON;
-				else if (!strcmp(optarg, "xmem"))
-					mp_alloc_type = MP_ALLOC_XMEM;
-				else if (!strcmp(optarg, "xmemhuge"))
-					mp_alloc_type = MP_ALLOC_XMEM_HUGE;
-				else if (!strcmp(optarg, "xbuf"))
-					mp_alloc_type = MP_ALLOC_XBUF;
-				else
-					rte_exit(EXIT_FAILURE,
-						"mp-alloc %s invalid - must be: "
-						"native, anon, xmem or xmemhuge\n",
-						 optarg);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "port-numa-config")) {
-				if (parse_portnuma_config(optarg))
-					rte_exit(EXIT_FAILURE,
-					   "invalid port-numa configuration\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "ring-numa-config"))
-				if (parse_ringnuma_config(optarg))
-					rte_exit(EXIT_FAILURE,
-					   "invalid ring-numa configuration\n");
-			if (!strcmp(lgopts[opt_idx].name, "socket-num")) {
-				n = atoi(optarg);
-				if (!new_socket_id((uint8_t)n)) {
-					socket_num = (uint8_t)n;
-				} else {
-					print_invalid_socket_id_error();
-					rte_exit(EXIT_FAILURE,
-						"Invalid socket id");
-				}
-			}
-			if (!strcmp(lgopts[opt_idx].name, "mbuf-size")) {
-				unsigned int mb_sz[MAX_SEGS_BUFFER_SPLIT];
-				unsigned int nb_segs, i;
-
-				nb_segs = parse_item_list(optarg, "mbuf-size",
-					MAX_SEGS_BUFFER_SPLIT, mb_sz, 0);
-				if (nb_segs <= 0)
-					rte_exit(EXIT_FAILURE,
-						 "bad mbuf-size\n");
-				for (i = 0; i < nb_segs; i++) {
-					if (mb_sz[i] <= 0 || mb_sz[i] > 0xFFFF)
-						rte_exit(EXIT_FAILURE,
-							 "mbuf-size should be "
-							 "> 0 and < 65536\n");
-					mbuf_data_size[i] = (uint16_t) mb_sz[i];
-				}
-				mbuf_data_size_n = nb_segs;
-			}
-			if (!strcmp(lgopts[opt_idx].name, "total-num-mbufs")) {
-				n = atoi(optarg);
-				if (n > MIN_TOTAL_NUM_MBUFS)
-					param_total_num_mbufs = (unsigned)n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "total-num-mbufs should be > %d\n",
-						 MIN_TOTAL_NUM_MBUFS);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "max-pkt-len")) {
-				n = atoi(optarg);
-				if (n >= RTE_ETHER_MIN_LEN)
-					max_rx_pkt_len = n;
-				else
+			break;
+		case TESTPMD_OPT_MBUF_SIZE_NUM: {
+			unsigned int mb_sz[MAX_SEGS_BUFFER_SPLIT];
+			unsigned int nb_segs, i;
+
+			nb_segs = parse_item_list(optarg, "mbuf-size",
+				MAX_SEGS_BUFFER_SPLIT, mb_sz, 0);
+			if (nb_segs <= 0)
+				rte_exit(EXIT_FAILURE,
+					"bad mbuf-size\n");
+			for (i = 0; i < nb_segs; i++) {
+				if (mb_sz[i] <= 0 || mb_sz[i] > 0xFFFF)
 					rte_exit(EXIT_FAILURE,
-						 "Invalid max-pkt-len=%d - should be > %d\n",
-						 n, RTE_ETHER_MIN_LEN);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "max-lro-pkt-size")) {
-				n = atoi(optarg);
-				rx_mode.max_lro_pkt_size = (uint32_t) n;
+						"mbuf-size should be "
+						"> 0 and < 65536\n");
+				mbuf_data_size[i] = (uint16_t) mb_sz[i];
 			}
+			mbuf_data_size_n = nb_segs;
+			break;
+		}
+		case TESTPMD_OPT_TOTAL_NUM_MBUFS_NUM:
+			n = atoi(optarg);
+			if (n > MIN_TOTAL_NUM_MBUFS)
+				param_total_num_mbufs = (unsigned int)n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"total-num-mbufs should be > %d\n",
+					MIN_TOTAL_NUM_MBUFS);
+			break;
+		case TESTPMD_OPT_MAX_PKT_LEN_NUM:
+			n = atoi(optarg);
+			if (n >= RTE_ETHER_MIN_LEN)
+				max_rx_pkt_len = n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"Invalid max-pkt-len=%d - should be > %d\n",
+					n, RTE_ETHER_MIN_LEN);
+			break;
+		case TESTPMD_OPT_MAX_LRO_PKT_SIZE_NUM:
+			n = atoi(optarg);
+			rx_mode.max_lro_pkt_size = (uint32_t) n;
+			break;
 #ifdef RTE_LIB_LATENCYSTATS
-			if (!strcmp(lgopts[opt_idx].name,
-				    "latencystats")) {
-				n = atoi(optarg);
-				if (n >= 0) {
-					latencystats_lcore_id = (lcoreid_t) n;
-					latencystats_enabled = 1;
-				} else
-					rte_exit(EXIT_FAILURE,
-						 "invalid lcore id %d for latencystats"
-						 " must be >= 0\n", n);
-			}
+		case TESTPMD_OPT_LATENCYSTATS_NUM:
+			n = atoi(optarg);
+			if (n >= 0) {
+				latencystats_lcore_id = (lcoreid_t) n;
+				latencystats_enabled = 1;
+			} else
+				rte_exit(EXIT_FAILURE,
+					"invalid lcore id %d for latencystats"
+					" must be >= 0\n", n);
+
+			break;
 #endif
 #ifdef RTE_LIB_BITRATESTATS
-			if (!strcmp(lgopts[opt_idx].name, "bitrate-stats")) {
-				n = atoi(optarg);
-				if (n >= 0) {
-					bitrate_lcore_id = (lcoreid_t) n;
-					bitrate_enabled = 1;
-				} else
-					rte_exit(EXIT_FAILURE,
-						 "invalid lcore id %d for bitrate stats"
-						 " must be >= 0\n", n);
-			}
+		case TESTPMD_OPT_BITRATE_STATS_NUM:
+			n = atoi(optarg);
+			if (n >= 0) {
+				bitrate_lcore_id = (lcoreid_t) n;
+				bitrate_enabled = 1;
+			} else
+				rte_exit(EXIT_FAILURE,
+					"invalid lcore id %d for bitrate stats"
+					" must be >= 0\n", n);
+			break;
 #endif
-			if (!strcmp(lgopts[opt_idx].name, "disable-crc-strip"))
-				rx_offloads |= RTE_ETH_RX_OFFLOAD_KEEP_CRC;
-			if (!strcmp(lgopts[opt_idx].name, "enable-lro"))
-				rx_offloads |= RTE_ETH_RX_OFFLOAD_TCP_LRO;
-			if (!strcmp(lgopts[opt_idx].name, "enable-scatter"))
-				rx_offloads |= RTE_ETH_RX_OFFLOAD_SCATTER;
-			if (!strcmp(lgopts[opt_idx].name, "enable-rx-cksum"))
-				rx_offloads |= RTE_ETH_RX_OFFLOAD_CHECKSUM;
-			if (!strcmp(lgopts[opt_idx].name,
-					"enable-rx-timestamp"))
-				rx_offloads |= RTE_ETH_RX_OFFLOAD_TIMESTAMP;
-			if (!strcmp(lgopts[opt_idx].name, "enable-hw-vlan"))
-				rx_offloads |= RTE_ETH_RX_OFFLOAD_VLAN;
-
-			if (!strcmp(lgopts[opt_idx].name,
-					"enable-hw-vlan-filter"))
-				rx_offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
-
-			if (!strcmp(lgopts[opt_idx].name,
-					"enable-hw-vlan-strip"))
-				rx_offloads |= RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
-
-			if (!strcmp(lgopts[opt_idx].name,
-					"enable-hw-vlan-extend"))
-				rx_offloads |= RTE_ETH_RX_OFFLOAD_VLAN_EXTEND;
-
-			if (!strcmp(lgopts[opt_idx].name,
-					"enable-hw-qinq-strip"))
-				rx_offloads |= RTE_ETH_RX_OFFLOAD_QINQ_STRIP;
-
-			if (!strcmp(lgopts[opt_idx].name, "enable-drop-en"))
-				rx_drop_en = 1;
-
-			if (!strcmp(lgopts[opt_idx].name, "disable-rss"))
-				rss_hf = 0;
-			if (!strcmp(lgopts[opt_idx].name, "port-topology")) {
-				if (!strcmp(optarg, "paired"))
-					port_topology = PORT_TOPOLOGY_PAIRED;
-				else if (!strcmp(optarg, "chained"))
-					port_topology = PORT_TOPOLOGY_CHAINED;
-				else if (!strcmp(optarg, "loop"))
-					port_topology = PORT_TOPOLOGY_LOOP;
-				else
-					rte_exit(EXIT_FAILURE, "port-topology %s invalid -"
-						 " must be: paired, chained or loop\n",
-						 optarg);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "forward-mode"))
-				set_pkt_forwarding_mode(optarg);
-			if (!strcmp(lgopts[opt_idx].name, "rss-ip"))
-				rss_hf = RTE_ETH_RSS_IP;
-			if (!strcmp(lgopts[opt_idx].name, "rss-udp"))
-				rss_hf = RTE_ETH_RSS_UDP;
-			if (!strcmp(lgopts[opt_idx].name, "rss-level-inner"))
-				rss_hf |= RTE_ETH_RSS_LEVEL_INNERMOST;
-			if (!strcmp(lgopts[opt_idx].name, "rss-level-outer"))
-				rss_hf |= RTE_ETH_RSS_LEVEL_OUTERMOST;
-			if (!strcmp(lgopts[opt_idx].name, "rxq")) {
-				n = atoi(optarg);
-				if (n >= 0 && check_nb_rxq((queueid_t)n) == 0)
-					nb_rxq = (queueid_t) n;
-				else
-					rte_exit(EXIT_FAILURE, "rxq %d invalid - must be"
-						  " >= 0 && <= %u\n", n,
-						  get_allowed_max_nb_rxq(&pid));
-				if (!nb_rxq && !nb_txq)
-					rte_exit(EXIT_FAILURE, "Either rx or tx queues should be non-zero\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "txq")) {
-				n = atoi(optarg);
-				if (n >= 0 && check_nb_txq((queueid_t)n) == 0)
-					nb_txq = (queueid_t) n;
-				else
-					rte_exit(EXIT_FAILURE, "txq %d invalid - must be"
-						  " >= 0 && <= %u\n", n,
-						  get_allowed_max_nb_txq(&pid));
-				if (!nb_rxq && !nb_txq)
-					rte_exit(EXIT_FAILURE, "Either rx or tx queues should be non-zero\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "hairpinq")) {
-				n = atoi(optarg);
-				if (n >= 0 &&
-				    check_nb_hairpinq((queueid_t)n) == 0)
-					nb_hairpinq = (queueid_t) n;
-				else
-					rte_exit(EXIT_FAILURE, "txq %d invalid - must be"
-						  " >= 0 && <= %u\n", n,
-						  get_allowed_max_nb_hairpinq
-						  (&pid));
-				if ((n + nb_txq) < 0 ||
-				    check_nb_txq((queueid_t)(n + nb_txq)) != 0)
-					rte_exit(EXIT_FAILURE, "txq + hairpinq "
-						 "%d invalid - must be"
-						  " >= 0 && <= %u\n",
-						  n + nb_txq,
-						  get_allowed_max_nb_txq(&pid));
-				if ((n + nb_rxq) < 0 ||
-				    check_nb_rxq((queueid_t)(n + nb_rxq)) != 0)
-					rte_exit(EXIT_FAILURE, "rxq + hairpinq "
-						 "%d invalid - must be"
-						  " >= 0 && <= %u\n",
-						  n + nb_rxq,
-						  get_allowed_max_nb_rxq(&pid));
-			}
-			if (!strcmp(lgopts[opt_idx].name, "hairpin-mode")) {
-				char *end = NULL;
-				unsigned int n;
-
-				errno = 0;
-				n = strtoul(optarg, &end, 0);
-				if (errno != 0 || end == optarg)
-					rte_exit(EXIT_FAILURE, "hairpin mode invalid\n");
+		case TESTPMD_OPT_DISABLE_CRC_STRIP_NUM:
+			rx_offloads |= RTE_ETH_RX_OFFLOAD_KEEP_CRC;
+			break;
+		case TESTPMD_OPT_ENABLE_LRO_NUM:
+			rx_offloads |= RTE_ETH_RX_OFFLOAD_TCP_LRO;
+			break;
+		case TESTPMD_OPT_ENABLE_SCATTER_NUM:
+			rx_offloads |= RTE_ETH_RX_OFFLOAD_SCATTER;
+			break;
+		case TESTPMD_OPT_ENABLE_RX_CKSUM_NUM:
+			rx_offloads |= RTE_ETH_RX_OFFLOAD_CHECKSUM;
+			break;
+		case TESTPMD_OPT_ENABLE_RX_TIMESTAMP_NUM:
+			rx_offloads |= RTE_ETH_RX_OFFLOAD_TIMESTAMP;
+			break;
+		case TESTPMD_OPT_ENABLE_HW_VLAN_NUM:
+			rx_offloads |= RTE_ETH_RX_OFFLOAD_VLAN;
+			break;
+		case TESTPMD_OPT_ENABLE_HW_VLAN_FILTER_NUM:
+			rx_offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
+			break;
+		case TESTPMD_OPT_ENABLE_HW_VLAN_STRIP_NUM:
+			rx_offloads |= RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
+			break;
+		case TESTPMD_OPT_ENABLE_HW_VLAN_EXTEND_NUM:
+			rx_offloads |= RTE_ETH_RX_OFFLOAD_VLAN_EXTEND;
+			break;
+		case TESTPMD_OPT_ENABLE_HW_QINQ_STRIP_NUM:
+			rx_offloads |= RTE_ETH_RX_OFFLOAD_QINQ_STRIP;
+			break;
+		case TESTPMD_OPT_ENABLE_DROP_EN_NUM:
+			rx_drop_en = 1;
+			break;
+		case TESTPMD_OPT_DISABLE_RSS_NUM:
+			rss_hf = 0;
+			break;
+		case TESTPMD_OPT_PORT_TOPOLOGY_NUM:
+			if (!strcmp(optarg, "paired"))
+				port_topology = PORT_TOPOLOGY_PAIRED;
+			else if (!strcmp(optarg, "chained"))
+				port_topology = PORT_TOPOLOGY_CHAINED;
+			else if (!strcmp(optarg, "loop"))
+				port_topology = PORT_TOPOLOGY_LOOP;
+			else
+				rte_exit(EXIT_FAILURE, "port-topology %s invalid -"
+					" must be: paired, chained or loop\n",
+					optarg);
+			break;
+		case TESTPMD_OPT_FORWARD_MODE_NUM:
+			set_pkt_forwarding_mode(optarg);
+			break;
+		case TESTPMD_OPT_RSS_IP_NUM:
+			rss_hf = RTE_ETH_RSS_IP;
+			break;
+		case TESTPMD_OPT_RSS_UDP_NUM:
+			rss_hf = RTE_ETH_RSS_UDP;
+			break;
+		case TESTPMD_OPT_RSS_LEVEL_INNER_NUM:
+			rss_hf |= RTE_ETH_RSS_LEVEL_INNERMOST;
+			break;
+		case TESTPMD_OPT_RSS_LEVEL_OUTER_NUM:
+			rss_hf |= RTE_ETH_RSS_LEVEL_OUTERMOST;
+			break;
+		case TESTPMD_OPT_RXQ_NUM:
+			n = atoi(optarg);
+			if (n >= 0 && check_nb_rxq((queueid_t)n) == 0)
+				nb_rxq = (queueid_t) n;
+			else
+				rte_exit(EXIT_FAILURE, "rxq %d invalid - must be"
+					" >= 0 && <= %u\n", n,
+					get_allowed_max_nb_rxq(&pid));
+			if (!nb_rxq && !nb_txq)
+				rte_exit(EXIT_FAILURE, "Either rx or tx queues should be non-zero\n");
+			break;
+		case TESTPMD_OPT_TXQ_NUM:
+			n = atoi(optarg);
+			if (n >= 0 && check_nb_txq((queueid_t)n) == 0)
+				nb_txq = (queueid_t) n;
+			else
+				rte_exit(EXIT_FAILURE, "txq %d invalid - must be"
+					" >= 0 && <= %u\n", n,
+					get_allowed_max_nb_txq(&pid));
+			if (!nb_rxq && !nb_txq)
+				rte_exit(EXIT_FAILURE, "Either rx or tx queues should be non-zero\n");
+			break;
+		case TESTPMD_OPT_HAIRPINQ_NUM:
+			n = atoi(optarg);
+			if (n >= 0 &&
+					check_nb_hairpinq((queueid_t)n) == 0)
+				nb_hairpinq = (queueid_t) n;
+			else
+				rte_exit(EXIT_FAILURE, "txq %d invalid - must be"
+					" >= 0 && <= %u\n", n,
+					get_allowed_max_nb_hairpinq
+					(&pid));
+			if ((n + nb_txq) < 0 ||
+					check_nb_txq((queueid_t)(n + nb_txq)) != 0)
+				rte_exit(EXIT_FAILURE, "txq + hairpinq "
+					"%d invalid - must be"
+					" >= 0 && <= %u\n",
+					n + nb_txq,
+					get_allowed_max_nb_txq(&pid));
+			if ((n + nb_rxq) < 0 ||
+					check_nb_rxq((queueid_t)(n + nb_rxq)) != 0)
+				rte_exit(EXIT_FAILURE, "rxq + hairpinq "
+					"%d invalid - must be"
+					" >= 0 && <= %u\n",
+					n + nb_rxq,
+					get_allowed_max_nb_rxq(&pid));
+			break;
+		case TESTPMD_OPT_HAIRPIN_MODE_NUM: {
+			char *end = NULL;
+			unsigned int n;
+
+			errno = 0;
+			n = strtoul(optarg, &end, 0);
+			if (errno != 0 || end == optarg)
+				rte_exit(EXIT_FAILURE, "hairpin mode invalid\n");
+			else
+				hairpin_mode = (uint32_t)n;
+			break;
+		}
+		case TESTPMD_OPT_BURST_NUM:
+			n = atoi(optarg);
+			if (n == 0) {
+				/* A burst size of zero means that the
+				 * PMD should be queried for
+				 * recommended Rx burst size. Since
+				 * testpmd uses a single size for all
+				 * ports, port 0 is queried for the
+				 * value, on the assumption that all
+				 * ports are of the same NIC model.
+				 */
+				ret = eth_dev_info_get_print_err(
+					0,
+					&dev_info);
+				if (ret != 0)
+					rec_nb_pkts = 0;
 				else
-					hairpin_mode = (uint32_t)n;
-			}
-			if (!strcmp(lgopts[opt_idx].name, "burst")) {
-				n = atoi(optarg);
-				if (n == 0) {
-					/* A burst size of zero means that the
-					 * PMD should be queried for
-					 * recommended Rx burst size. Since
-					 * testpmd uses a single size for all
-					 * ports, port 0 is queried for the
-					 * value, on the assumption that all
-					 * ports are of the same NIC model.
-					 */
-					ret = eth_dev_info_get_print_err(
-								0,
-								&dev_info);
-					if (ret != 0)
-						rec_nb_pkts = 0;
-					else
-						rec_nb_pkts = dev_info
+					rec_nb_pkts = dev_info
 						.default_rxportconf.burst_size;
 
-					if (rec_nb_pkts == 0)
-						rte_exit(EXIT_FAILURE,
-							"PMD does not recommend a burst size. "
-							"Provided value must be between "
-							"1 and %d\n", MAX_PKT_BURST);
-					else if (rec_nb_pkts > MAX_PKT_BURST)
-						rte_exit(EXIT_FAILURE,
-							"PMD recommended burst size of %d"
-							" exceeds maximum value of %d\n",
-							rec_nb_pkts, MAX_PKT_BURST);
-					printf("Using PMD-provided burst value of %d\n",
-						rec_nb_pkts);
-					nb_pkt_per_burst = rec_nb_pkts;
-				} else if (n > MAX_PKT_BURST)
-					rte_exit(EXIT_FAILURE,
-						"burst must be between1 and %d\n",
-						MAX_PKT_BURST);
-				else
-					nb_pkt_per_burst = (uint16_t) n;
-			}
-			if (!strcmp(lgopts[opt_idx].name, "flowgen-clones")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					nb_pkt_flowgen_clones = (uint16_t) n;
-				else
+				if (rec_nb_pkts == 0)
 					rte_exit(EXIT_FAILURE,
-						 "clones must be >= 0 and <= current burst\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "flowgen-flows")) {
-				n = atoi(optarg);
-				if (n > 0)
-					nb_flows_flowgen = (int) n;
-				else
+						"PMD does not recommend a burst size. "
+						"Provided value must be between "
+						"1 and %d\n", MAX_PKT_BURST);
+				else if (rec_nb_pkts > MAX_PKT_BURST)
 					rte_exit(EXIT_FAILURE,
-						 "flows must be >= 1\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "mbcache")) {
-				n = atoi(optarg);
-				if ((n >= 0) &&
-				    (n <= RTE_MEMPOOL_CACHE_MAX_SIZE))
-					mb_mempool_cache = (uint16_t) n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "mbcache must be >= 0 and <= %d\n",
-						 RTE_MEMPOOL_CACHE_MAX_SIZE);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "txfreet")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					tx_free_thresh = (int16_t)n;
-				else
-					rte_exit(EXIT_FAILURE, "txfreet must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "txrst")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					tx_rs_thresh = (int16_t)n;
-				else
-					rte_exit(EXIT_FAILURE, "txrst must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "rxd")) {
-				n = atoi(optarg);
-				if (n > 0) {
-					if (rx_free_thresh >= n)
-						rte_exit(EXIT_FAILURE,
-							 "rxd must be > "
-							 "rx_free_thresh(%d)\n",
-							 (int)rx_free_thresh);
-					else
-						nb_rxd = (uint16_t) n;
-				} else
+						"PMD recommended burst size of %d"
+						" exceeds maximum value of %d\n",
+						rec_nb_pkts, MAX_PKT_BURST);
+				printf("Using PMD-provided burst value of %d\n",
+					rec_nb_pkts);
+				nb_pkt_per_burst = rec_nb_pkts;
+			} else if (n > MAX_PKT_BURST)
+				rte_exit(EXIT_FAILURE,
+					"burst must be between1 and %d\n",
+					MAX_PKT_BURST);
+			else
+				nb_pkt_per_burst = (uint16_t) n;
+			break;
+		case TESTPMD_OPT_FLOWGEN_CLONES_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				nb_pkt_flowgen_clones = (uint16_t) n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"clones must be >= 0 and <= current burst\n");
+			break;
+		case TESTPMD_OPT_FLOWGEN_FLOWS_NUM:
+			n = atoi(optarg);
+			if (n > 0)
+				nb_flows_flowgen = (int) n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"flows must be >= 1\n");
+			break;
+		case TESTPMD_OPT_MBCACHE_NUM:
+			n = atoi(optarg);
+			if ((n >= 0) &&
+					(n <= RTE_MEMPOOL_CACHE_MAX_SIZE))
+				mb_mempool_cache = (uint16_t) n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"mbcache must be >= 0 and <= %d\n",
+					RTE_MEMPOOL_CACHE_MAX_SIZE);
+			break;
+		case TESTPMD_OPT_TXFREET_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				tx_free_thresh = (int16_t)n;
+			else
+				rte_exit(EXIT_FAILURE, "txfreet must be >= 0\n");
+			break;
+		case TESTPMD_OPT_TXRST_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				tx_rs_thresh = (int16_t)n;
+			else
+				rte_exit(EXIT_FAILURE, "txrst must be >= 0\n");
+			break;
+		case TESTPMD_OPT_RXD_NUM:
+			n = atoi(optarg);
+			if (n > 0) {
+				if (rx_free_thresh >= n)
 					rte_exit(EXIT_FAILURE,
-						 "rxd(%d) invalid - must be > 0\n",
-						 n);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "txd")) {
-				n = atoi(optarg);
-				if (n > 0)
-					nb_txd = (uint16_t) n;
-				else
-					rte_exit(EXIT_FAILURE, "txd must be in > 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "txpt")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					tx_pthresh = (int8_t)n;
-				else
-					rte_exit(EXIT_FAILURE, "txpt must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "txht")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					tx_hthresh = (int8_t)n;
+						"rxd must be > "
+						"rx_free_thresh(%d)\n",
+						(int)rx_free_thresh);
 				else
-					rte_exit(EXIT_FAILURE, "txht must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "txwt")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					tx_wthresh = (int8_t)n;
-				else
-					rte_exit(EXIT_FAILURE, "txwt must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "rxpt")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					rx_pthresh = (int8_t)n;
-				else
-					rte_exit(EXIT_FAILURE, "rxpt must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "rxht")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					rx_hthresh = (int8_t)n;
-				else
-					rte_exit(EXIT_FAILURE, "rxht must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "rxwt")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					rx_wthresh = (int8_t)n;
-				else
-					rte_exit(EXIT_FAILURE, "rxwt must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "rxfreet")) {
+					nb_rxd = (uint16_t) n;
+			} else
+				rte_exit(EXIT_FAILURE,
+					"rxd(%d) invalid - must be > 0\n",
+					n);
+			break;
+		case TESTPMD_OPT_TXD_NUM:
+			n = atoi(optarg);
+			if (n > 0)
+				nb_txd = (uint16_t) n;
+			else
+				rte_exit(EXIT_FAILURE, "txd must be in > 0\n");
+			break;
+		case TESTPMD_OPT_TXPT_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				tx_pthresh = (int8_t)n;
+			else
+				rte_exit(EXIT_FAILURE, "txpt must be >= 0\n");
+			break;
+		case TESTPMD_OPT_TXHT_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				tx_hthresh = (int8_t)n;
+			else
+				rte_exit(EXIT_FAILURE, "txht must be >= 0\n");
+			break;
+		case TESTPMD_OPT_TXWT_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				tx_wthresh = (int8_t)n;
+			else
+				rte_exit(EXIT_FAILURE, "txwt must be >= 0\n");
+			break;
+		case TESTPMD_OPT_RXPT_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				rx_pthresh = (int8_t)n;
+			else
+				rte_exit(EXIT_FAILURE, "rxpt must be >= 0\n");
+			break;
+		case TESTPMD_OPT_RXHT_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				rx_hthresh = (int8_t)n;
+			else
+				rte_exit(EXIT_FAILURE, "rxht must be >= 0\n");
+			break;
+		case TESTPMD_OPT_RXWT_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				rx_wthresh = (int8_t)n;
+			else
+				rte_exit(EXIT_FAILURE, "rxwt must be >= 0\n");
+			break;
+		case TESTPMD_OPT_RXFREET_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				rx_free_thresh = (int16_t)n;
+			else
+				rte_exit(EXIT_FAILURE, "rxfreet must be >= 0\n");
+			break;
+		case TESTPMD_OPT_RXOFFS_NUM: {
+			unsigned int seg_off[MAX_SEGS_BUFFER_SPLIT];
+			unsigned int nb_offs;
+
+			nb_offs = parse_item_list
+				(optarg, "rxpkt offsets",
+				MAX_SEGS_BUFFER_SPLIT,
+				seg_off, 0);
+			if (nb_offs > 0)
+				set_rx_pkt_offsets(seg_off, nb_offs);
+			else
+				rte_exit(EXIT_FAILURE, "bad rxoffs\n");
+			break;
+		}
+		case TESTPMD_OPT_RXPKTS_NUM: {
+			unsigned int seg_len[MAX_SEGS_BUFFER_SPLIT];
+			unsigned int nb_segs;
+
+			nb_segs = parse_item_list
+				(optarg, "rxpkt segments",
+				MAX_SEGS_BUFFER_SPLIT,
+				seg_len, 0);
+			if (nb_segs > 0)
+				set_rx_pkt_segments(seg_len, nb_segs);
+			else
+				rte_exit(EXIT_FAILURE, "bad rxpkts\n");
+			break;
+		}
+		case TESTPMD_OPT_RXHDRS_NUM: {
+			unsigned int seg_hdrs[MAX_SEGS_BUFFER_SPLIT];
+			unsigned int nb_segs;
+
+			nb_segs = parse_hdrs_list
+				(optarg, "rxpkt segments",
+				MAX_SEGS_BUFFER_SPLIT,
+				seg_hdrs);
+			if (nb_segs > 0)
+				set_rx_pkt_hdrs(seg_hdrs, nb_segs);
+			else
+				rte_exit(EXIT_FAILURE, "bad rxpkts\n");
+			break;
+		}
+		case TESTPMD_OPT_TXPKTS_NUM: {
+			unsigned int seg_lengths[RTE_MAX_SEGS_PER_PKT];
+			unsigned int nb_segs;
+
+			nb_segs = parse_item_list(optarg, "txpkt segments",
+				RTE_MAX_SEGS_PER_PKT, seg_lengths, 0);
+			if (nb_segs > 0)
+				set_tx_pkt_segments(seg_lengths, nb_segs);
+			else
+				rte_exit(EXIT_FAILURE, "bad txpkts\n");
+			break;
+		}
+		case TESTPMD_OPT_MULTI_RX_MEMPOOL_NUM:
+			multi_rx_mempool = 1;
+			break;
+		case TESTPMD_OPT_TXONLY_MULTI_FLOW_NUM:
+			txonly_multi_flow = 1;
+			break;
+		case TESTPMD_OPT_RXQ_SHARE_NUM:
+			if (optarg == NULL) {
+				rxq_share = UINT32_MAX;
+			} else {
 				n = atoi(optarg);
 				if (n >= 0)
-					rx_free_thresh = (int16_t)n;
-				else
-					rte_exit(EXIT_FAILURE, "rxfreet must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "rxoffs")) {
-				unsigned int seg_off[MAX_SEGS_BUFFER_SPLIT];
-				unsigned int nb_offs;
-
-				nb_offs = parse_item_list
-						(optarg, "rxpkt offsets",
-						 MAX_SEGS_BUFFER_SPLIT,
-						 seg_off, 0);
-				if (nb_offs > 0)
-					set_rx_pkt_offsets(seg_off, nb_offs);
-				else
-					rte_exit(EXIT_FAILURE, "bad rxoffs\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "rxpkts")) {
-				unsigned int seg_len[MAX_SEGS_BUFFER_SPLIT];
-				unsigned int nb_segs;
-				nb_segs = parse_item_list
-						(optarg, "rxpkt segments",
-						 MAX_SEGS_BUFFER_SPLIT,
-						 seg_len, 0);
-				if (nb_segs > 0)
-					set_rx_pkt_segments(seg_len, nb_segs);
-				else
-					rte_exit(EXIT_FAILURE, "bad rxpkts\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "rxhdrs")) {
-				unsigned int seg_hdrs[MAX_SEGS_BUFFER_SPLIT];
-				unsigned int nb_segs;
-
-				nb_segs = parse_hdrs_list
-						(optarg, "rxpkt segments",
-						MAX_SEGS_BUFFER_SPLIT,
-						seg_hdrs);
-				if (nb_segs > 0)
-					set_rx_pkt_hdrs(seg_hdrs, nb_segs);
+					rxq_share = (uint32_t)n;
 				else
-					rte_exit(EXIT_FAILURE, "bad rxpkts\n");
+					rte_exit(EXIT_FAILURE, "rxq-share must be >= 0\n");
 			}
-			if (!strcmp(lgopts[opt_idx].name, "txpkts")) {
-				unsigned seg_lengths[RTE_MAX_SEGS_PER_PKT];
-				unsigned int nb_segs;
-
-				nb_segs = parse_item_list(optarg, "txpkt segments",
-						RTE_MAX_SEGS_PER_PKT, seg_lengths, 0);
-				if (nb_segs > 0)
-					set_tx_pkt_segments(seg_lengths, nb_segs);
-				else
-					rte_exit(EXIT_FAILURE, "bad txpkts\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "multi-rx-mempool"))
-				multi_rx_mempool = 1;
-			if (!strcmp(lgopts[opt_idx].name, "txonly-multi-flow"))
-				txonly_multi_flow = 1;
-			if (!strcmp(lgopts[opt_idx].name, "rxq-share")) {
-				if (optarg == NULL) {
-					rxq_share = UINT32_MAX;
-				} else {
-					n = atoi(optarg);
-					if (n >= 0)
-						rxq_share = (uint32_t)n;
-					else
-						rte_exit(EXIT_FAILURE, "rxq-share must be >= 0\n");
-				}
-			}
-			if (!strcmp(lgopts[opt_idx].name, "no-flush-rx"))
-				no_flush_rx = 1;
-			if (!strcmp(lgopts[opt_idx].name, "eth-link-speed")) {
-				n = atoi(optarg);
-				if (n >= 0 && parse_link_speed(n) > 0)
-					eth_link_speed = parse_link_speed(n);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "disable-link-check"))
-				no_link_check = 1;
-			if (!strcmp(lgopts[opt_idx].name, "disable-device-start"))
-				no_device_start = 1;
-			if (!strcmp(lgopts[opt_idx].name, "no-lsc-interrupt"))
-				lsc_interrupt = 0;
-			if (!strcmp(lgopts[opt_idx].name, "no-rmv-interrupt"))
-				rmv_interrupt = 0;
-			if (!strcmp(lgopts[opt_idx].name, "flow-isolate-all"))
-				flow_isolate_all = 1;
-			if (!strcmp(lgopts[opt_idx].name, "disable-flow-flush"))
-				no_flow_flush = 1;
-			if (!strcmp(lgopts[opt_idx].name, "tx-offloads")) {
-				char *end = NULL;
-				n = strtoull(optarg, &end, 16);
-				if (n >= 0)
-					tx_offloads = (uint64_t)n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "tx-offloads must be >= 0\n");
+			break;
+		case TESTPMD_OPT_NO_FLUSH_RX_NUM:
+			no_flush_rx = 1;
+			break;
+		case TESTPMD_OPT_ETH_LINK_SPEED_NUM:
+			n = atoi(optarg);
+			if (n >= 0 && parse_link_speed(n) > 0)
+				eth_link_speed = parse_link_speed(n);
+			break;
+		case TESTPMD_OPT_DISABLE_LINK_CHECK_NUM:
+			no_link_check = 1;
+			break;
+		case TESTPMD_OPT_DISABLE_DEVICE_START_NUM:
+			no_device_start = 1;
+			break;
+		case TESTPMD_OPT_NO_LSC_INTERRUPT_NUM:
+			lsc_interrupt = 0;
+			break;
+		case TESTPMD_OPT_NO_RMV_INTERRUPT_NUM:
+			rmv_interrupt = 0;
+			break;
+		case TESTPMD_OPT_FLOW_ISOLATE_ALL_NUM:
+			flow_isolate_all = 1;
+			break;
+		case TESTPMD_OPT_DISABLE_FLOW_FLUSH_NUM:
+			no_flow_flush = 1;
+			break;
+		case TESTPMD_OPT_TX_OFFLOADS_NUM: {
+			char *end = NULL;
+
+			n = strtoull(optarg, &end, 16);
+			if (n >= 0)
+				tx_offloads = (uint64_t)n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"tx-offloads must be >= 0\n");
+			break;
+		}
+		case TESTPMD_OPT_RX_OFFLOADS_NUM: {
+			char *end = NULL;
+
+			n = strtoull(optarg, &end, 16);
+			if (n >= 0)
+				rx_offloads = (uint64_t)n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"rx-offloads must be >= 0\n");
+			break;
+		}
+		case TESTPMD_OPT_VXLAN_GPE_PORT_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				vxlan_gpe_udp_port = (uint16_t)n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"vxlan-gpe-port must be >= 0\n");
+			break;
+		case TESTPMD_OPT_GENEVE_PARSED_PORT_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				geneve_udp_port = (uint16_t)n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"geneve-parsed-port must be >= 0\n");
+			break;
+		case TESTPMD_OPT_PRINT_EVENT_NUM:
+			if (parse_event_printing_config(optarg, 1)) {
+				rte_exit(EXIT_FAILURE,
+					"invalid print-event argument\n");
 			}
-
-			if (!strcmp(lgopts[opt_idx].name, "rx-offloads")) {
-				char *end = NULL;
-				n = strtoull(optarg, &end, 16);
-				if (n >= 0)
-					rx_offloads = (uint64_t)n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "rx-offloads must be >= 0\n");
+			break;
+		case TESTPMD_OPT_MASK_EVENT_NUM:
+			if (parse_event_printing_config(optarg, 0)) {
+				rte_exit(EXIT_FAILURE,
+					"invalid mask-event argument\n");
 			}
+			break;
+		case TESTPMD_OPT_HOT_PLUG_NUM:
+			hot_plug = 1;
+			break;
+		case TESTPMD_OPT_MLOCKALL_NUM:
+			do_mlockall = 1;
+			break;
+		case TESTPMD_OPT_NO_MLOCKALL_NUM:
+			do_mlockall = 0;
+			break;
+		case TESTPMD_OPT_NOISY_TX_SW_BUFFER_SIZE_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				noisy_tx_sw_bufsz = n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"noisy-tx-sw-buffer-size must be >= 0\n");
+			break;
+		case TESTPMD_OPT_NOISY_TX_SW_BUFFER_FLUSHTIME_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				noisy_tx_sw_buf_flush_time = n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"noisy-tx-sw-buffer-flushtime must be >= 0\n");
+			break;
+		case TESTPMD_OPT_NOISY_LKUP_MEMORY_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				noisy_lkup_mem_sz = n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"noisy-lkup-memory must be >= 0\n");
+			break;
+		case TESTPMD_OPT_NOISY_LKUP_NUM_WRITES_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				noisy_lkup_num_writes = n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"noisy-lkup-num-writes must be >= 0\n");
+			break;
+		case TESTPMD_OPT_NOISY_LKUP_NUM_READS_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				noisy_lkup_num_reads = n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"noisy-lkup-num-reads must be >= 0\n");
+			break;
+		case TESTPMD_OPT_NOISY_LKUP_NUM_READS_WRITES_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				noisy_lkup_num_reads_writes = n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"noisy-lkup-num-reads-writes must be >= 0\n");
+			break;
+		case TESTPMD_OPT_NOISY_FORWARD_MODE_NUM: {
+			unsigned int i;
 
-			if (!strcmp(lgopts[opt_idx].name, "vxlan-gpe-port")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					vxlan_gpe_udp_port = (uint16_t)n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "vxlan-gpe-port must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name,
-				    "geneve-parsed-port")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					geneve_udp_port = (uint16_t)n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "geneve-parsed-port must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "print-event"))
-				if (parse_event_printing_config(optarg, 1)) {
-					rte_exit(EXIT_FAILURE,
-						 "invalid print-event argument\n");
+			for (i = 0; i < NOISY_FWD_MODE_MAX; i++) {
+				if (!strcmp(optarg, noisy_fwd_mode_desc[i])) {
+					noisy_fwd_mode = i;
+					break;
 				}
-			if (!strcmp(lgopts[opt_idx].name, "mask-event"))
-				if (parse_event_printing_config(optarg, 0)) {
-					rte_exit(EXIT_FAILURE,
-						 "invalid mask-event argument\n");
-				}
-			if (!strcmp(lgopts[opt_idx].name, "hot-plug"))
-				hot_plug = 1;
-			if (!strcmp(lgopts[opt_idx].name, "mlockall"))
-				do_mlockall = 1;
-			if (!strcmp(lgopts[opt_idx].name, "no-mlockall"))
-				do_mlockall = 0;
-			if (!strcmp(lgopts[opt_idx].name,
-				    "noisy-tx-sw-buffer-size")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					noisy_tx_sw_bufsz = n;
-				else
-					rte_exit(EXIT_FAILURE,
-						"noisy-tx-sw-buffer-size must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name,
-				    "noisy-tx-sw-buffer-flushtime")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					noisy_tx_sw_buf_flush_time = n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "noisy-tx-sw-buffer-flushtime must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name,
-				    "noisy-lkup-memory")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					noisy_lkup_mem_sz = n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "noisy-lkup-memory must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name,
-				    "noisy-lkup-num-writes")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					noisy_lkup_num_writes = n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "noisy-lkup-num-writes must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name,
-				    "noisy-lkup-num-reads")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					noisy_lkup_num_reads = n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "noisy-lkup-num-reads must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name,
-				    "noisy-lkup-num-reads-writes")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					noisy_lkup_num_reads_writes = n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "noisy-lkup-num-reads-writes must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name,
-				    "noisy-forward-mode")) {
-				int i;
-				for (i = 0; i < NOISY_FWD_MODE_MAX; i++)
-					if (!strcmp(optarg, noisy_fwd_mode_desc[i])) {
-						noisy_fwd_mode = i;
-						break;
-					}
-				if (i == NOISY_FWD_MODE_MAX)
-					rte_exit(EXIT_FAILURE, "noisy-forward-mode %s invalid,"
-						 " must be a valid noisy-forward-mode value\n",
-						 optarg);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "no-iova-contig"))
-				mempool_flags = RTE_MEMPOOL_F_NO_IOVA_CONTIG;
-
-			if (!strcmp(lgopts[opt_idx].name, "rx-mq-mode")) {
-				char *end = NULL;
-				n = strtoul(optarg, &end, 16);
-				if (n >= 0 && n <= RTE_ETH_MQ_RX_VMDQ_DCB_RSS)
-					rx_mq_mode = (enum rte_eth_rx_mq_mode)n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "rx-mq-mode must be >= 0 and <= %d\n",
-						 RTE_ETH_MQ_RX_VMDQ_DCB_RSS);
 			}
-			if (!strcmp(lgopts[opt_idx].name, "record-core-cycles"))
-				record_core_cycles = 1;
-			if (!strcmp(lgopts[opt_idx].name, "record-burst-stats"))
-				record_burst_stats = 1;
-			if (!strcmp(lgopts[opt_idx].name, PARAM_NUM_PROCS))
-				num_procs = atoi(optarg);
-			if (!strcmp(lgopts[opt_idx].name, PARAM_PROC_ID))
-				proc_id = atoi(optarg);
+			if (i == NOISY_FWD_MODE_MAX)
+				rte_exit(EXIT_FAILURE, "noisy-forward-mode %s invalid,"
+					 " must be a valid noisy-forward-mode value\n",
+					 optarg);
 			break;
-		case 'h':
-			usage(argv[0]);
-			exit(EXIT_SUCCESS);
+		}
+		case TESTPMD_OPT_NO_IOVA_CONTIG_NUM:
+			mempool_flags = RTE_MEMPOOL_F_NO_IOVA_CONTIG;
+			break;
+		case TESTPMD_OPT_RX_MQ_MODE_NUM: {
+			char *end = NULL;
+
+			n = strtoul(optarg, &end, 16);
+			if (n >= 0 && n <= RTE_ETH_MQ_RX_VMDQ_DCB_RSS)
+				rx_mq_mode = (enum rte_eth_rx_mq_mode)n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"rx-mq-mode must be >= 0 and <= %d\n",
+					RTE_ETH_MQ_RX_VMDQ_DCB_RSS);
+			break;
+		}
+		case TESTPMD_OPT_RECORD_CORE_CYCLES_NUM:
+			record_core_cycles = 1;
+			break;
+		case TESTPMD_OPT_RECORD_BURST_STATS_NUM:
+			record_burst_stats = 1;
+			break;
+		case TESTPMD_OPT_NUM_PROCS_NUM:
+			num_procs = atoi(optarg);
+			break;
+		case TESTPMD_OPT_PROC_ID_NUM:
+			proc_id = atoi(optarg);
 			break;
 		default:
 			usage(argv[0]);
@@ -1510,9 +1750,9 @@ launch_args_parse(int argc, char** argv)
 
 	if (proc_id >= (int)num_procs)
 		rte_exit(EXIT_FAILURE,
-			 "The multi-process option '%s(%d)' should be less than '%s(%u)'\n",
-			 PARAM_PROC_ID, proc_id,
-			 PARAM_NUM_PROCS, num_procs);
+			"The multi-process option '%s(%d)' should be less than '%s(%u)'\n",
+			TESTPMD_OPT_PROC_ID, proc_id,
+			TESTPMD_OPT_NUM_PROCS, num_procs);
 
 	/* Set offload configuration from command line parameters. */
 	rx_mode.offloads = rx_offloads;
-- 
2.44.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 1/4] app/testpmd: fix stats-period option check
  2024-03-08 14:48 ` [PATCH 1/4] app/testpmd: fix stats-period option check David Marchand
@ 2024-03-12 16:43   ` Ferruh Yigit
  0 siblings, 0 replies; 35+ messages in thread
From: Ferruh Yigit @ 2024-03-12 16:43 UTC (permalink / raw)
  To: David Marchand, dev
  Cc: stable, Aman Singh, Yuying Zhang, Pablo de Lara, Jingjing Wu

On 3/8/2024 2:48 PM, David Marchand wrote:
> Rather than silently ignore an invalid value, raise an error for
> stats-period user input.
> 
> Fixes: cfea1f3048d1 ("app/testpmd: print statistics periodically")
> Cc: stable@dpdk.org
> 
> Signed-off-by: David Marchand <david.marchand@redhat.com>
>

Acked-by: Ferruh Yigit <ferruh.yigit@amd.com>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 2/4] app/testpmd: fix burst option parsing
  2024-03-08 14:48 ` [PATCH 2/4] app/testpmd: fix burst option parsing David Marchand
@ 2024-03-12 16:47   ` Ferruh Yigit
  2024-03-13  7:24     ` David Marchand
  0 siblings, 1 reply; 35+ messages in thread
From: Ferruh Yigit @ 2024-03-12 16:47 UTC (permalink / raw)
  To: David Marchand, dev
  Cc: stable, Aman Singh, Yuying Zhang, Ivan Ilchenko,
	Andrew Rybchenko, Bernard Iremonger

On 3/8/2024 2:48 PM, David Marchand wrote:
> rte_eth_dev_info_get() is not supposed to fail for a valid port_id, but
> for the theoretical case when it would fail, raise an error rather than
> skip subsequent options.
> 
> Fixes: 6f51deb903b2 ("app/testpmd: check status of getting ethdev info")
> Cc: stable@dpdk.org
> 
> Signed-off-by: David Marchand <david.marchand@redhat.com>
> ---
>  app/test-pmd/parameters.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
> index d715750bb8..8c21744009 100644
> --- a/app/test-pmd/parameters.c
> +++ b/app/test-pmd/parameters.c
> @@ -1128,9 +1128,9 @@ launch_args_parse(int argc, char** argv)
>  								0,
>  								&dev_info);
>  					if (ret != 0)
> -						return;
> -
> -					rec_nb_pkts = dev_info
> +						rec_nb_pkts = 0;
> +					else
> +						rec_nb_pkts = dev_info
>  						.default_rxportconf.burst_size;
>  
>  					if (rec_nb_pkts == 0)

'eth_dev_info_get_print_err()' already fail, but it may not be very
clear to the user,
OK to print a failure log, but setting 'rec_nb_pkts = 0;' as above also
will generate an error message that also may be confusing to the user.

What about print an explicit error message for the
'eth_dev_info_get_print_err()' failed case?


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 3/4] app/testpmd: check queue count for related options
  2024-03-08 14:48 ` [PATCH 3/4] app/testpmd: check queue count for related options David Marchand
@ 2024-03-12 16:59   ` Ferruh Yigit
  2024-03-13  7:37     ` David Marchand
  0 siblings, 1 reply; 35+ messages in thread
From: Ferruh Yigit @ 2024-03-12 16:59 UTC (permalink / raw)
  To: David Marchand, dev; +Cc: Aman Singh, Yuying Zhang

On 3/8/2024 2:48 PM, David Marchand wrote:
> Checking the number of rxq/txq in the middle of option parsing is
> confusing. Move the check where nb_rxq / nb_txq are modified.
> 
> Signed-off-by: David Marchand <david.marchand@redhat.com>
> ---
>  app/test-pmd/parameters.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
> index 8c21744009..271f0c995a 100644
> --- a/app/test-pmd/parameters.c
> +++ b/app/test-pmd/parameters.c
> @@ -1063,6 +1063,8 @@ launch_args_parse(int argc, char** argv)
>  					rte_exit(EXIT_FAILURE, "rxq %d invalid - must be"
>  						  " >= 0 && <= %u\n", n,
>  						  get_allowed_max_nb_rxq(&pid));
> +				if (!nb_rxq && !nb_txq)
> +					rte_exit(EXIT_FAILURE, "Either rx or tx queues should be non-zero\n");
>  			}
>  			if (!strcmp(lgopts[opt_idx].name, "txq")) {
>  				n = atoi(optarg);
> @@ -1072,6 +1074,8 @@ launch_args_parse(int argc, char** argv)
>  					rte_exit(EXIT_FAILURE, "txq %d invalid - must be"
>  						  " >= 0 && <= %u\n", n,
>  						  get_allowed_max_nb_txq(&pid));
> +				if (!nb_rxq && !nb_txq)
> +					rte_exit(EXIT_FAILURE, "Either rx or tx queues should be non-zero\n");
>  			}
>  			if (!strcmp(lgopts[opt_idx].name, "hairpinq")) {
>  				n = atoi(optarg);
> @@ -1098,10 +1102,6 @@ launch_args_parse(int argc, char** argv)
>  						  n + nb_rxq,
>  						  get_allowed_max_nb_rxq(&pid));
>  			}
> -			if (!nb_rxq && !nb_txq) {
> -				rte_exit(EXIT_FAILURE, "Either rx or tx queues should "
> -						"be non-zero\n");
> -			}
>  			if (!strcmp(lgopts[opt_idx].name, "hairpin-mode")) {
>  				char *end = NULL;
>  				unsigned int n;

There is already a runtime check for queues [1], perhaps we can remove
it altogether from arg parse.

Also I think the order of the 'hairpinq' and queue number parameter
processing depends on order user provided, so this may not be very
reliable anyway.


[1]
https://git.dpdk.org/dpdk/tree/app/test-pmd/testpmd.c?h=v24.03-rc2#n4621

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 4/4] app/testpmd: enhance getopt_long usage
  2024-03-08 14:48 ` [PATCH 4/4] app/testpmd: enhance getopt_long usage David Marchand
@ 2024-03-12 17:03   ` Ferruh Yigit
  2024-03-13 16:51     ` David Marchand
  0 siblings, 1 reply; 35+ messages in thread
From: Ferruh Yigit @ 2024-03-12 17:03 UTC (permalink / raw)
  To: David Marchand, dev; +Cc: Aman Singh, Yuying Zhang

On 3/8/2024 2:48 PM, David Marchand wrote:
> This is a cleanup similar to previous ones in EAL and examples.
> Instead of using strcmp for every long options while getopt_long already
> did such parsing, rely on getopt_long return value.
> 
> Note for reviewers: this patch is best reviewed once applied locally and
> displayed with git show -w.
> 

Thanks for the cleanup, it was needed.


> Signed-off-by: David Marchand <david.marchand@redhat.com>
> ---
>  app/test-pmd/parameters.c | 1928 +++++++++++++++++++++----------------
>  1 file changed, 1084 insertions(+), 844 deletions(-)
> 
> diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
> index 271f0c995a..58f43cb5a8 100644
> --- a/app/test-pmd/parameters.c
> +++ b/app/test-pmd/parameters.c
> @@ -40,6 +40,346 @@
>  
>  #include "testpmd.h"
>  
> +enum {
> +	/* long options mapped to a short option */
> +#define TESTPMD_OPT_AUTO_START "auto-start"
> +	TESTPMD_OPT_AUTO_START_NUM = 'a',
> +#define TESTPMD_OPT_HELP "help"
> +	TESTPMD_OPT_HELP_NUM = 'h',
> +#define TESTPMD_OPT_INTERACTIVE "interactive"
> +	TESTPMD_OPT_INTERACTIVE_NUM = 'i',
> +
> +	/* first long only option value must be >= 256 */
> +	TESTPMD_OPT_LONG_MIN_NUM = 256,
>

This is to be able to use all short options, not sure if this requires a
comment.

<...>

> +};
> +
> +static struct option long_options[] = {
>

Can it be constant?

> +	{ TESTPMD_OPT_AUTO_START, 0, NULL, TESTPMD_OPT_AUTO_START_NUM },
>

In original version "auto-start" long version is enabled only if
'RTE_LIB_CMDLINE' enabled, not sure why, but not for short version, I
think there is a confusion.

OK to remove RTE_LIB_CMDLINE requirement for 'auto-start' but perhaps
better to have it in separate patch, what do you think?


> +	{ TESTPMD_OPT_HELP, 0, NULL, TESTPMD_OPT_HELP_NUM },
> +#ifdef RTE_LIB_CMDLINE
> +	{ TESTPMD_OPT_INTERACTIVE, 0, NULL, TESTPMD_OPT_INTERACTIVE_NUM },
> +	{ TESTPMD_OPT_CMDLINE_FILE, 1, NULL, TESTPMD_OPT_CMDLINE_FILE},
>

What about using 'no_argument' & 'required_argument' instead of '0' &
'1', but I guess it will make lines too big,
as flag will be always NULL in this approach, what about defining macros
for arg and no_arg, like:
```
#define ARG(name) (name), required_argument, NULL, name##_NUM
#define NOARG(name) (name), no_argument, NULL, name##_NUM
#define OPTARG(name) (name), optional_argument, NULL, name##_NUM

{ NOARG(TESTPMD_OPT_INTERACTIVE) },
{ ARG(TESTPMD_OPT_CMDLINE_FILE) },
```

> +	{ TESTPMD_OPT_ETH_PEERS_CONFIGFILE, 1, NULL, TESTPMD_OPT_ETH_PEERS_CONFIGFILE_NUM },
> +	{ TESTPMD_OPT_ETH_PEER, 1, NULL, TESTPMD_OPT_ETH_PEER_NUM },
>

These long options are within "#ifdef RTE_LIB_CMDLINE" block, I don't
know why, I guess above two can work without cmdline library.

<...>

> -
>  	argvopt = argv;
>  

Why 'argvopt' is required, why not use 'argv' directly?

<...>

>  #ifdef RTE_LIB_CMDLINE
> ...
> +		case TESTPMD_OPT_ETH_PEER_NUM: {
> +			char *port_end;
>  
> -				if (rte_ether_unformat_addr(port_end,
> -						&peer_eth_addrs[n]) < 0)
> -					rte_exit(EXIT_FAILURE,
> -						 "Invalid ethernet address: %s\n",
> -						 port_end);
> -				nb_peer_eth_addrs++;
> -			}
> +			errno = 0;
> +			n = strtoul(optarg, &port_end, 10);
> +			if (errno != 0 || port_end == optarg || *port_end++ != ',')
> +				rte_exit(EXIT_FAILURE,
> +					"Invalid eth-peer: %s", optarg);
> +			if (n >= RTE_MAX_ETHPORTS)
> +				rte_exit(EXIT_FAILURE,
> +					"eth-peer: port %d >= RTE_MAX_ETHPORTS(%d)\n",
> +					n, RTE_MAX_ETHPORTS);
> +
> +			if (rte_ether_unformat_addr(port_end,
> +					&peer_eth_addrs[n]) < 0)
> +				rte_exit(EXIT_FAILURE,
> +					"Invalid ethernet address: %s\n",
> +					port_end);
> +			nb_peer_eth_addrs++;
> +			break;
> +		}
>  #endif
>

Similar to the 'struct option long_options' comment, I think expect from
"interactive" & "cmdline-file", rest can be moved out of "#ifdef
RTE_LIB_CMDLINE" block, but not this patch in different patch.

<...>

>  		default:
>  			usage(argv[0]);
>

It is not shown in the patch, to print the error case it uses:
`fprintf(stderr, "Invalid option: %s\n", argv[optind]);`

But as far as I can see 'optind' is the next arg to call, so instead it
should be 'optind - 1'.


And just after while loop, there is "if (optind != argc)" check, I don't
see when this check will be hit, so it looks useless.



^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 2/4] app/testpmd: fix burst option parsing
  2024-03-12 16:47   ` Ferruh Yigit
@ 2024-03-13  7:24     ` David Marchand
  2024-03-13 10:37       ` Ferruh Yigit
  0 siblings, 1 reply; 35+ messages in thread
From: David Marchand @ 2024-03-13  7:24 UTC (permalink / raw)
  To: Ferruh Yigit
  Cc: dev, stable, Aman Singh, Yuying Zhang, Ivan Ilchenko,
	Andrew Rybchenko, Bernard Iremonger

On Tue, Mar 12, 2024 at 5:47 PM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>
> On 3/8/2024 2:48 PM, David Marchand wrote:
> > rte_eth_dev_info_get() is not supposed to fail for a valid port_id, but
> > for the theoretical case when it would fail, raise an error rather than
> > skip subsequent options.
> >
> > Fixes: 6f51deb903b2 ("app/testpmd: check status of getting ethdev info")
> > Cc: stable@dpdk.org
> >
> > Signed-off-by: David Marchand <david.marchand@redhat.com>
> > ---
> >  app/test-pmd/parameters.c | 6 +++---
> >  1 file changed, 3 insertions(+), 3 deletions(-)
> >
> > diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
> > index d715750bb8..8c21744009 100644
> > --- a/app/test-pmd/parameters.c
> > +++ b/app/test-pmd/parameters.c
> > @@ -1128,9 +1128,9 @@ launch_args_parse(int argc, char** argv)
> >                                                               0,
> >                                                               &dev_info);
> >                                       if (ret != 0)
> > -                                             return;
> > -
> > -                                     rec_nb_pkts = dev_info
> > +                                             rec_nb_pkts = 0;
> > +                                     else
> > +                                             rec_nb_pkts = dev_info
> >                                               .default_rxportconf.burst_size;
> >
> >                                       if (rec_nb_pkts == 0)
>
> 'eth_dev_info_get_print_err()' already fail, but it may not be very
> clear to the user,
> OK to print a failure log, but setting 'rec_nb_pkts = 0;' as above also
> will generate an error message that also may be confusing to the user.
>
> What about print an explicit error message for the
> 'eth_dev_info_get_print_err()' failed case?

rte_exit(EXIT_FAILURE, "Failed to retrieve device info, this is
probably a driver bug. "
        "To workaround this issue, please provide a value between 1
and %d\n", MAX_PKT_BURST);

Does it work for you?


-- 
David Marchand


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 3/4] app/testpmd: check queue count for related options
  2024-03-12 16:59   ` Ferruh Yigit
@ 2024-03-13  7:37     ` David Marchand
  2024-03-13 10:42       ` Ferruh Yigit
  0 siblings, 1 reply; 35+ messages in thread
From: David Marchand @ 2024-03-13  7:37 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: dev, Aman Singh, Yuying Zhang

On Tue, Mar 12, 2024 at 5:59 PM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>
> On 3/8/2024 2:48 PM, David Marchand wrote:
> > Checking the number of rxq/txq in the middle of option parsing is
> > confusing. Move the check where nb_rxq / nb_txq are modified.
> >
> > Signed-off-by: David Marchand <david.marchand@redhat.com>
> > ---
> >  app/test-pmd/parameters.c | 8 ++++----
> >  1 file changed, 4 insertions(+), 4 deletions(-)
> >
> > diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
> > index 8c21744009..271f0c995a 100644
> > --- a/app/test-pmd/parameters.c
> > +++ b/app/test-pmd/parameters.c
> > @@ -1063,6 +1063,8 @@ launch_args_parse(int argc, char** argv)
> >                                       rte_exit(EXIT_FAILURE, "rxq %d invalid - must be"
> >                                                 " >= 0 && <= %u\n", n,
> >                                                 get_allowed_max_nb_rxq(&pid));
> > +                             if (!nb_rxq && !nb_txq)
> > +                                     rte_exit(EXIT_FAILURE, "Either rx or tx queues should be non-zero\n");
> >                       }
> >                       if (!strcmp(lgopts[opt_idx].name, "txq")) {
> >                               n = atoi(optarg);
> > @@ -1072,6 +1074,8 @@ launch_args_parse(int argc, char** argv)
> >                                       rte_exit(EXIT_FAILURE, "txq %d invalid - must be"
> >                                                 " >= 0 && <= %u\n", n,
> >                                                 get_allowed_max_nb_txq(&pid));
> > +                             if (!nb_rxq && !nb_txq)
> > +                                     rte_exit(EXIT_FAILURE, "Either rx or tx queues should be non-zero\n");
> >                       }
> >                       if (!strcmp(lgopts[opt_idx].name, "hairpinq")) {
> >                               n = atoi(optarg);
> > @@ -1098,10 +1102,6 @@ launch_args_parse(int argc, char** argv)
> >                                                 n + nb_rxq,
> >                                                 get_allowed_max_nb_rxq(&pid));
> >                       }
> > -                     if (!nb_rxq && !nb_txq) {
> > -                             rte_exit(EXIT_FAILURE, "Either rx or tx queues should "
> > -                                             "be non-zero\n");
> > -                     }
> >                       if (!strcmp(lgopts[opt_idx].name, "hairpin-mode")) {
> >                               char *end = NULL;
> >                               unsigned int n;
>
> There is already a runtime check for queues [1], perhaps we can remove
> it altogether from arg parse.

Good catch.

This other check comes after parsing args, so I suspect it is just dead code.
I guess I'll change it into a rte_exit(EXIT_FAILURE..).
Is this what you propose?


>
> Also I think the order of the 'hairpinq' and queue number parameter
> processing depends on order user provided, so this may not be very
> reliable anyway.

Indeed.


-- 
David Marchand


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 2/4] app/testpmd: fix burst option parsing
  2024-03-13  7:24     ` David Marchand
@ 2024-03-13 10:37       ` Ferruh Yigit
  2024-03-13 11:13         ` David Marchand
  0 siblings, 1 reply; 35+ messages in thread
From: Ferruh Yigit @ 2024-03-13 10:37 UTC (permalink / raw)
  To: David Marchand
  Cc: dev, stable, Aman Singh, Yuying Zhang, Ivan Ilchenko,
	Andrew Rybchenko, Bernard Iremonger

On 3/13/2024 7:24 AM, David Marchand wrote:
> On Tue, Mar 12, 2024 at 5:47 PM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>>
>> On 3/8/2024 2:48 PM, David Marchand wrote:
>>> rte_eth_dev_info_get() is not supposed to fail for a valid port_id, but
>>> for the theoretical case when it would fail, raise an error rather than
>>> skip subsequent options.
>>>
>>> Fixes: 6f51deb903b2 ("app/testpmd: check status of getting ethdev info")
>>> Cc: stable@dpdk.org
>>>
>>> Signed-off-by: David Marchand <david.marchand@redhat.com>
>>> ---
>>>  app/test-pmd/parameters.c | 6 +++---
>>>  1 file changed, 3 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
>>> index d715750bb8..8c21744009 100644
>>> --- a/app/test-pmd/parameters.c
>>> +++ b/app/test-pmd/parameters.c
>>> @@ -1128,9 +1128,9 @@ launch_args_parse(int argc, char** argv)
>>>                                                               0,
>>>                                                               &dev_info);
>>>                                       if (ret != 0)
>>> -                                             return;
>>> -
>>> -                                     rec_nb_pkts = dev_info
>>> +                                             rec_nb_pkts = 0;
>>> +                                     else
>>> +                                             rec_nb_pkts = dev_info
>>>                                               .default_rxportconf.burst_size;
>>>
>>>                                       if (rec_nb_pkts == 0)
>>
>> 'eth_dev_info_get_print_err()' already fail, but it may not be very
>> clear to the user,
>> OK to print a failure log, but setting 'rec_nb_pkts = 0;' as above also
>> will generate an error message that also may be confusing to the user.
>>
>> What about print an explicit error message for the
>> 'eth_dev_info_get_print_err()' failed case?
> 
> rte_exit(EXIT_FAILURE, "Failed to retrieve device info, this is
> probably a driver bug. "
>         "To workaround this issue, please provide a value between 1
> and %d\n", MAX_PKT_BURST);
> 
> Does it work for you?
> 
> 

'eth_dev_info_get_print_err()' already logs error about getting device
info, but driver recommended 'burst' setting failed information is missing.

What about more direct,
"Failed to get driver recommended burst size, please provide a value
between 1 and MAX_PKT_BURST"

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 3/4] app/testpmd: check queue count for related options
  2024-03-13  7:37     ` David Marchand
@ 2024-03-13 10:42       ` Ferruh Yigit
  2024-03-13 11:10         ` David Marchand
  0 siblings, 1 reply; 35+ messages in thread
From: Ferruh Yigit @ 2024-03-13 10:42 UTC (permalink / raw)
  To: David Marchand; +Cc: dev, Aman Singh, Yuying Zhang

On 3/13/2024 7:37 AM, David Marchand wrote:
> On Tue, Mar 12, 2024 at 5:59 PM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>>
>> On 3/8/2024 2:48 PM, David Marchand wrote:
>>> Checking the number of rxq/txq in the middle of option parsing is
>>> confusing. Move the check where nb_rxq / nb_txq are modified.
>>>
>>> Signed-off-by: David Marchand <david.marchand@redhat.com>
>>> ---
>>>  app/test-pmd/parameters.c | 8 ++++----
>>>  1 file changed, 4 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
>>> index 8c21744009..271f0c995a 100644
>>> --- a/app/test-pmd/parameters.c
>>> +++ b/app/test-pmd/parameters.c
>>> @@ -1063,6 +1063,8 @@ launch_args_parse(int argc, char** argv)
>>>                                       rte_exit(EXIT_FAILURE, "rxq %d invalid - must be"
>>>                                                 " >= 0 && <= %u\n", n,
>>>                                                 get_allowed_max_nb_rxq(&pid));
>>> +                             if (!nb_rxq && !nb_txq)
>>> +                                     rte_exit(EXIT_FAILURE, "Either rx or tx queues should be non-zero\n");
>>>                       }
>>>                       if (!strcmp(lgopts[opt_idx].name, "txq")) {
>>>                               n = atoi(optarg);
>>> @@ -1072,6 +1074,8 @@ launch_args_parse(int argc, char** argv)
>>>                                       rte_exit(EXIT_FAILURE, "txq %d invalid - must be"
>>>                                                 " >= 0 && <= %u\n", n,
>>>                                                 get_allowed_max_nb_txq(&pid));
>>> +                             if (!nb_rxq && !nb_txq)
>>> +                                     rte_exit(EXIT_FAILURE, "Either rx or tx queues should be non-zero\n");
>>>                       }
>>>                       if (!strcmp(lgopts[opt_idx].name, "hairpinq")) {
>>>                               n = atoi(optarg);
>>> @@ -1098,10 +1102,6 @@ launch_args_parse(int argc, char** argv)
>>>                                                 n + nb_rxq,
>>>                                                 get_allowed_max_nb_rxq(&pid));
>>>                       }
>>> -                     if (!nb_rxq && !nb_txq) {
>>> -                             rte_exit(EXIT_FAILURE, "Either rx or tx queues should "
>>> -                                             "be non-zero\n");
>>> -                     }
>>>                       if (!strcmp(lgopts[opt_idx].name, "hairpin-mode")) {
>>>                               char *end = NULL;
>>>                               unsigned int n;
>>
>> There is already a runtime check for queues [1], perhaps we can remove
>> it altogether from arg parse.
> 
> Good catch.
> 
> This other check comes after parsing args, so I suspect it is just dead code.
> I guess I'll change it into a rte_exit(EXIT_FAILURE..).
> Is this what you propose?
> 

I think that check is the main check for nb_rxq and nb_txq.

The one you removed is for the 'hairpinq' parameter, which is not a very
common usecase.
But nb_rxq and nb_txq requirement is very common and it is protected in
the main after parameter parsing.

I am not suggesting adding 'rte_exit()' for that case, probably it will
fail in some other part and error log can provide the required hint.
And I am worried if it breaks some unexpected usecase with exit.

I was just thinking the check can be removed from 'hairpinq' parameter.

> 
>>
>> Also I think the order of the 'hairpinq' and queue number parameter
>> processing depends on order user provided, so this may not be very
>> reliable anyway.
> 
> Indeed.
> 
> 


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 3/4] app/testpmd: check queue count for related options
  2024-03-13 10:42       ` Ferruh Yigit
@ 2024-03-13 11:10         ` David Marchand
  2024-03-13 12:18           ` Ferruh Yigit
  0 siblings, 1 reply; 35+ messages in thread
From: David Marchand @ 2024-03-13 11:10 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: dev, Aman Singh, Yuying Zhang

On Wed, Mar 13, 2024 at 11:52 AM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>
> On 3/13/2024 7:37 AM, David Marchand wrote:
> > On Tue, Mar 12, 2024 at 5:59 PM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
> >>
> >> On 3/8/2024 2:48 PM, David Marchand wrote:
> >>> Checking the number of rxq/txq in the middle of option parsing is
> >>> confusing. Move the check where nb_rxq / nb_txq are modified.
> >>>
> >>> Signed-off-by: David Marchand <david.marchand@redhat.com>
> >>> ---
> >>>  app/test-pmd/parameters.c | 8 ++++----
> >>>  1 file changed, 4 insertions(+), 4 deletions(-)
> >>>
> >>> diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
> >>> index 8c21744009..271f0c995a 100644
> >>> --- a/app/test-pmd/parameters.c
> >>> +++ b/app/test-pmd/parameters.c
> >>> @@ -1063,6 +1063,8 @@ launch_args_parse(int argc, char** argv)
> >>>                                       rte_exit(EXIT_FAILURE, "rxq %d invalid - must be"
> >>>                                                 " >= 0 && <= %u\n", n,
> >>>                                                 get_allowed_max_nb_rxq(&pid));
> >>> +                             if (!nb_rxq && !nb_txq)
> >>> +                                     rte_exit(EXIT_FAILURE, "Either rx or tx queues should be non-zero\n");
> >>>                       }
> >>>                       if (!strcmp(lgopts[opt_idx].name, "txq")) {
> >>>                               n = atoi(optarg);
> >>> @@ -1072,6 +1074,8 @@ launch_args_parse(int argc, char** argv)
> >>>                                       rte_exit(EXIT_FAILURE, "txq %d invalid - must be"
> >>>                                                 " >= 0 && <= %u\n", n,
> >>>                                                 get_allowed_max_nb_txq(&pid));
> >>> +                             if (!nb_rxq && !nb_txq)
> >>> +                                     rte_exit(EXIT_FAILURE, "Either rx or tx queues should be non-zero\n");
> >>>                       }
> >>>                       if (!strcmp(lgopts[opt_idx].name, "hairpinq")) {
> >>>                               n = atoi(optarg);
> >>> @@ -1098,10 +1102,6 @@ launch_args_parse(int argc, char** argv)
> >>>                                                 n + nb_rxq,
> >>>                                                 get_allowed_max_nb_rxq(&pid));
> >>>                       }
> >>> -                     if (!nb_rxq && !nb_txq) {
> >>> -                             rte_exit(EXIT_FAILURE, "Either rx or tx queues should "
> >>> -                                             "be non-zero\n");
> >>> -                     }
> >>>                       if (!strcmp(lgopts[opt_idx].name, "hairpin-mode")) {
> >>>                               char *end = NULL;
> >>>                               unsigned int n;
> >>
> >> There is already a runtime check for queues [1], perhaps we can remove
> >> it altogether from arg parse.
> >
> > Good catch.
> >
> > This other check comes after parsing args, so I suspect it is just dead code.
> > I guess I'll change it into a rte_exit(EXIT_FAILURE..).
> > Is this what you propose?
> >
>
> I think that check is the main check for nb_rxq and nb_txq.
>
> The one you removed is for the 'hairpinq' parameter, which is not a very
> common usecase.

This check was present before hairpinq introduction.
https://git.dpdk.org/dpdk/commit/app/test-pmd/parameters.c?id=1c69df45f8c6b727c3b6a78e13f81225c090dde2


This check in parsing args is hit when setting incorrect rxq / txq config.
This has nothing to do with hairpinq parsing.

$ build-mini/app/dpdk-testpmd -c 3 --no-huge -m 40 -a 0:0.0 --vdev
net_null1 --vdev net_null2 -- --no-mlockall --total-num-mbufs=2048 -ia
--rxq 0 --txq 0
EAL: Detected CPU lcores: 16
EAL: Detected NUMA nodes: 1
EAL: Detected static linkage of DPDK
EAL: Multi-process socket /run/user/114840/dpdk/rte/mp_socket
EAL: Selected IOVA mode 'VA'
TELEMETRY: No legacy callbacks, legacy socket not created
Interactive-mode selected
Auto-start selected
EAL: Error - exiting with code: 1
  Cause: Either rx or tx queues should be non-zero
Port 0 is closed
Port 1 is closed



> But nb_rxq and nb_txq requirement is very common and it is protected in
> the main after parameter parsing.

Sorry, I am not following.

>
> I am not suggesting adding 'rte_exit()' for that case, probably it will
> fail in some other part and error log can provide the required hint.
> And I am worried if it breaks some unexpected usecase with exit.

If we simply remove this check as you suggest:
$ build-mini/app/dpdk-testpmd -c 3 --no-huge -m 40 -a 0:0.0 --vdev
net_null1 --vdev net_null2 -- --no-mlockall --total-num-mbufs=2048 -ia
--rxq 0 --txq 0
EAL: Detected CPU lcores: 16
EAL: Detected NUMA nodes: 1
EAL: Detected static linkage of DPDK
EAL: Multi-process socket /run/user/114840/dpdk/rte/mp_socket
EAL: Selected IOVA mode 'VA'
TELEMETRY: No legacy callbacks, legacy socket not created
Interactive-mode selected
Auto-start selected
Warning: Either rx or tx queues should be non-zero
^^^
Pointless log.

testpmd: create a new mbuf pool <mb_pool_0>: n=2048, size=2176, socket=0
testpmd: preferred mempool ops selected: ring_mp_mc
Fail: Cannot allocate fwd streams as number of queues is 0
Segmentation fault (core dumped)
^^^
And crash.


-- 
David Marchand


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 2/4] app/testpmd: fix burst option parsing
  2024-03-13 10:37       ` Ferruh Yigit
@ 2024-03-13 11:13         ` David Marchand
  2024-03-13 12:09           ` Ferruh Yigit
  0 siblings, 1 reply; 35+ messages in thread
From: David Marchand @ 2024-03-13 11:13 UTC (permalink / raw)
  To: Ferruh Yigit
  Cc: dev, stable, Aman Singh, Yuying Zhang, Ivan Ilchenko,
	Andrew Rybchenko, Bernard Iremonger

On Wed, Mar 13, 2024 at 11:37 AM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>
> On 3/13/2024 7:24 AM, David Marchand wrote:
> > On Tue, Mar 12, 2024 at 5:47 PM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
> >>
> >> On 3/8/2024 2:48 PM, David Marchand wrote:
> >>> rte_eth_dev_info_get() is not supposed to fail for a valid port_id, but
> >>> for the theoretical case when it would fail, raise an error rather than
> >>> skip subsequent options.
> >>>
> >>> Fixes: 6f51deb903b2 ("app/testpmd: check status of getting ethdev info")
> >>> Cc: stable@dpdk.org
> >>>
> >>> Signed-off-by: David Marchand <david.marchand@redhat.com>
> >>> ---
> >>>  app/test-pmd/parameters.c | 6 +++---
> >>>  1 file changed, 3 insertions(+), 3 deletions(-)
> >>>
> >>> diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
> >>> index d715750bb8..8c21744009 100644
> >>> --- a/app/test-pmd/parameters.c
> >>> +++ b/app/test-pmd/parameters.c
> >>> @@ -1128,9 +1128,9 @@ launch_args_parse(int argc, char** argv)
> >>>                                                               0,
> >>>                                                               &dev_info);
> >>>                                       if (ret != 0)
> >>> -                                             return;
> >>> -
> >>> -                                     rec_nb_pkts = dev_info
> >>> +                                             rec_nb_pkts = 0;
> >>> +                                     else
> >>> +                                             rec_nb_pkts = dev_info
> >>>                                               .default_rxportconf.burst_size;
> >>>
> >>>                                       if (rec_nb_pkts == 0)
> >>
> >> 'eth_dev_info_get_print_err()' already fail, but it may not be very
> >> clear to the user,
> >> OK to print a failure log, but setting 'rec_nb_pkts = 0;' as above also
> >> will generate an error message that also may be confusing to the user.
> >>
> >> What about print an explicit error message for the
> >> 'eth_dev_info_get_print_err()' failed case?
> >
> > rte_exit(EXIT_FAILURE, "Failed to retrieve device info, this is
> > probably a driver bug. "
> >         "To workaround this issue, please provide a value between 1
> > and %d\n", MAX_PKT_BURST);
> >
> > Does it work for you?
> >
> >
>
> 'eth_dev_info_get_print_err()' already logs error about getting device
> info, but driver recommended 'burst' setting failed information is missing.
>
> What about more direct,
> "Failed to get driver recommended burst size, please provide a value
> between 1 and MAX_PKT_BURST"

Which is really close to the existing log message.

                                        if (rec_nb_pkts == 0)
                                                rte_exit(EXIT_FAILURE,
                                                        "PMD does not
recommend a burst size. "
                                                        "Provided
value must be between "
                                                        "1 and %d\n",
MAX_PKT_BURST);

I am unconvinced, but if you think strongly for this, I won't debate more.


-- 
David Marchand


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 2/4] app/testpmd: fix burst option parsing
  2024-03-13 11:13         ` David Marchand
@ 2024-03-13 12:09           ` Ferruh Yigit
  2024-03-13 16:32             ` Stephen Hemminger
  0 siblings, 1 reply; 35+ messages in thread
From: Ferruh Yigit @ 2024-03-13 12:09 UTC (permalink / raw)
  To: David Marchand
  Cc: dev, stable, Aman Singh, Yuying Zhang, Ivan Ilchenko,
	Andrew Rybchenko, Bernard Iremonger

On 3/13/2024 11:13 AM, David Marchand wrote:
> On Wed, Mar 13, 2024 at 11:37 AM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>>
>> On 3/13/2024 7:24 AM, David Marchand wrote:
>>> On Tue, Mar 12, 2024 at 5:47 PM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>>>>
>>>> On 3/8/2024 2:48 PM, David Marchand wrote:
>>>>> rte_eth_dev_info_get() is not supposed to fail for a valid port_id, but
>>>>> for the theoretical case when it would fail, raise an error rather than
>>>>> skip subsequent options.
>>>>>
>>>>> Fixes: 6f51deb903b2 ("app/testpmd: check status of getting ethdev info")
>>>>> Cc: stable@dpdk.org
>>>>>
>>>>> Signed-off-by: David Marchand <david.marchand@redhat.com>
>>>>> ---
>>>>>  app/test-pmd/parameters.c | 6 +++---
>>>>>  1 file changed, 3 insertions(+), 3 deletions(-)
>>>>>
>>>>> diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
>>>>> index d715750bb8..8c21744009 100644
>>>>> --- a/app/test-pmd/parameters.c
>>>>> +++ b/app/test-pmd/parameters.c
>>>>> @@ -1128,9 +1128,9 @@ launch_args_parse(int argc, char** argv)
>>>>>                                                               0,
>>>>>                                                               &dev_info);
>>>>>                                       if (ret != 0)
>>>>> -                                             return;
>>>>> -
>>>>> -                                     rec_nb_pkts = dev_info
>>>>> +                                             rec_nb_pkts = 0;
>>>>> +                                     else
>>>>> +                                             rec_nb_pkts = dev_info
>>>>>                                               .default_rxportconf.burst_size;
>>>>>
>>>>>                                       if (rec_nb_pkts == 0)
>>>>
>>>> 'eth_dev_info_get_print_err()' already fail, but it may not be very
>>>> clear to the user,
>>>> OK to print a failure log, but setting 'rec_nb_pkts = 0;' as above also
>>>> will generate an error message that also may be confusing to the user.
>>>>
>>>> What about print an explicit error message for the
>>>> 'eth_dev_info_get_print_err()' failed case?
>>>
>>> rte_exit(EXIT_FAILURE, "Failed to retrieve device info, this is
>>> probably a driver bug. "
>>>         "To workaround this issue, please provide a value between 1
>>> and %d\n", MAX_PKT_BURST);
>>>
>>> Does it work for you?
>>>
>>>
>>
>> 'eth_dev_info_get_print_err()' already logs error about getting device
>> info, but driver recommended 'burst' setting failed information is missing.
>>
>> What about more direct,
>> "Failed to get driver recommended burst size, please provide a value
>> between 1 and MAX_PKT_BURST"
> 
> Which is really close to the existing log message.
> 
>                                         if (rec_nb_pkts == 0)
>                                                 rte_exit(EXIT_FAILURE,
>                                                         "PMD does not
> recommend a burst size. "
>                                                         "Provided
> value must be between "
>                                                         "1 and %d\n",
> MAX_PKT_BURST);
> 
> I am unconvinced, but if you think strongly for this, I won't debate more.
> 
> 

Yes it is close, and I don't have strong opinion on this,

But existing message says "PMD does not recommend a burst size.", I
think this may be confusing for user.

If I see that message I would either debug relevant driver code or
communicate with driver maintainer for it. But that is not the case,
just failed to get recommended burst size and problem is in testpmd.

Anyway, my concern is existing message can be misleading for user.


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 3/4] app/testpmd: check queue count for related options
  2024-03-13 11:10         ` David Marchand
@ 2024-03-13 12:18           ` Ferruh Yigit
  0 siblings, 0 replies; 35+ messages in thread
From: Ferruh Yigit @ 2024-03-13 12:18 UTC (permalink / raw)
  To: David Marchand; +Cc: dev, Aman Singh, Yuying Zhang

On 3/13/2024 11:10 AM, David Marchand wrote:
> On Wed, Mar 13, 2024 at 11:52 AM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>>
>> On 3/13/2024 7:37 AM, David Marchand wrote:
>>> On Tue, Mar 12, 2024 at 5:59 PM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>>>>
>>>> On 3/8/2024 2:48 PM, David Marchand wrote:
>>>>> Checking the number of rxq/txq in the middle of option parsing is
>>>>> confusing. Move the check where nb_rxq / nb_txq are modified.
>>>>>
>>>>> Signed-off-by: David Marchand <david.marchand@redhat.com>
>>>>> ---
>>>>>  app/test-pmd/parameters.c | 8 ++++----
>>>>>  1 file changed, 4 insertions(+), 4 deletions(-)
>>>>>
>>>>> diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
>>>>> index 8c21744009..271f0c995a 100644
>>>>> --- a/app/test-pmd/parameters.c
>>>>> +++ b/app/test-pmd/parameters.c
>>>>> @@ -1063,6 +1063,8 @@ launch_args_parse(int argc, char** argv)
>>>>>                                       rte_exit(EXIT_FAILURE, "rxq %d invalid - must be"
>>>>>                                                 " >= 0 && <= %u\n", n,
>>>>>                                                 get_allowed_max_nb_rxq(&pid));
>>>>> +                             if (!nb_rxq && !nb_txq)
>>>>> +                                     rte_exit(EXIT_FAILURE, "Either rx or tx queues should be non-zero\n");
>>>>>                       }
>>>>>                       if (!strcmp(lgopts[opt_idx].name, "txq")) {
>>>>>                               n = atoi(optarg);
>>>>> @@ -1072,6 +1074,8 @@ launch_args_parse(int argc, char** argv)
>>>>>                                       rte_exit(EXIT_FAILURE, "txq %d invalid - must be"
>>>>>                                                 " >= 0 && <= %u\n", n,
>>>>>                                                 get_allowed_max_nb_txq(&pid));
>>>>> +                             if (!nb_rxq && !nb_txq)
>>>>> +                                     rte_exit(EXIT_FAILURE, "Either rx or tx queues should be non-zero\n");
>>>>>                       }
>>>>>                       if (!strcmp(lgopts[opt_idx].name, "hairpinq")) {
>>>>>                               n = atoi(optarg);
>>>>> @@ -1098,10 +1102,6 @@ launch_args_parse(int argc, char** argv)
>>>>>                                                 n + nb_rxq,
>>>>>                                                 get_allowed_max_nb_rxq(&pid));
>>>>>                       }
>>>>> -                     if (!nb_rxq && !nb_txq) {
>>>>> -                             rte_exit(EXIT_FAILURE, "Either rx or tx queues should "
>>>>> -                                             "be non-zero\n");
>>>>> -                     }
>>>>>                       if (!strcmp(lgopts[opt_idx].name, "hairpin-mode")) {
>>>>>                               char *end = NULL;
>>>>>                               unsigned int n;
>>>>
>>>> There is already a runtime check for queues [1], perhaps we can remove
>>>> it altogether from arg parse.
>>>
>>> Good catch.
>>>
>>> This other check comes after parsing args, so I suspect it is just dead code.
>>> I guess I'll change it into a rte_exit(EXIT_FAILURE..).
>>> Is this what you propose?
>>>
>>
>> I think that check is the main check for nb_rxq and nb_txq.
>>
>> The one you removed is for the 'hairpinq' parameter, which is not a very
>> common usecase.
> 
> This check was present before hairpinq introduction.
> https://git.dpdk.org/dpdk/commit/app/test-pmd/parameters.c?id=1c69df45f8c6b727c3b6a78e13f81225c090dde2
> 
> 
> This check in parsing args is hit when setting incorrect rxq / txq config.
> This has nothing to do with hairpinq parsing.
> 

Right. I misread the code.

Probably check was just after rxq/txq parsing but 'hairpinq' parsing get
in the way and left check in even more odd location.


> $ build-mini/app/dpdk-testpmd -c 3 --no-huge -m 40 -a 0:0.0 --vdev
> net_null1 --vdev net_null2 -- --no-mlockall --total-num-mbufs=2048 -ia
> --rxq 0 --txq 0
> EAL: Detected CPU lcores: 16
> EAL: Detected NUMA nodes: 1
> EAL: Detected static linkage of DPDK
> EAL: Multi-process socket /run/user/114840/dpdk/rte/mp_socket
> EAL: Selected IOVA mode 'VA'
> TELEMETRY: No legacy callbacks, legacy socket not created
> Interactive-mode selected
> Auto-start selected
> EAL: Error - exiting with code: 1
>   Cause: Either rx or tx queues should be non-zero
> Port 0 is closed
> Port 1 is closed
> 
> 
> 
>> But nb_rxq and nb_txq requirement is very common and it is protected in
>> the main after parameter parsing.
> 
> Sorry, I am not following.
> 
>>
>> I am not suggesting adding 'rte_exit()' for that case, probably it will
>> fail in some other part and error log can provide the required hint.
>> And I am worried if it breaks some unexpected usecase with exit.
> 
> If we simply remove this check as you suggest:
> $ build-mini/app/dpdk-testpmd -c 3 --no-huge -m 40 -a 0:0.0 --vdev
> net_null1 --vdev net_null2 -- --no-mlockall --total-num-mbufs=2048 -ia
> --rxq 0 --txq 0
> EAL: Detected CPU lcores: 16
> EAL: Detected NUMA nodes: 1
> EAL: Detected static linkage of DPDK
> EAL: Multi-process socket /run/user/114840/dpdk/rte/mp_socket
> EAL: Selected IOVA mode 'VA'
> TELEMETRY: No legacy callbacks, legacy socket not created
> Interactive-mode selected
> Auto-start selected
> Warning: Either rx or tx queues should be non-zero
> ^^^
> Pointless log.
> 
> testpmd: create a new mbuf pool <mb_pool_0>: n=2048, size=2176, socket=0
> testpmd: preferred mempool ops selected: ring_mp_mc
> Fail: Cannot allocate fwd streams as number of queues is 0
> Segmentation fault (core dumped)
> ^^^
> And crash.
> 
> 

I was thinking check is only in the scope of hairpinq.

In this case you are right, check in main is redundant. We can either
- have this patch, plus remove the check in main()
- or remove the check in parameter parsing and add 'rte_exit()' to the
one in main.
Both OK to me.


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 2/4] app/testpmd: fix burst option parsing
  2024-03-13 12:09           ` Ferruh Yigit
@ 2024-03-13 16:32             ` Stephen Hemminger
  0 siblings, 0 replies; 35+ messages in thread
From: Stephen Hemminger @ 2024-03-13 16:32 UTC (permalink / raw)
  To: Ferruh Yigit
  Cc: David Marchand, dev, stable, Aman Singh, Yuying Zhang,
	Ivan Ilchenko, Andrew Rybchenko, Bernard Iremonger

On Wed, 13 Mar 2024 12:09:01 +0000
Ferruh Yigit <ferruh.yigit@amd.com> wrote:

> > Which is really close to the existing log message.
> > 
> >                                         if (rec_nb_pkts == 0)
> >                                                 rte_exit(EXIT_FAILURE,
> >                                                         "PMD does not
> > recommend a burst size. "
> >                                                         "Provided
> > value must be between "
> >                                                         "1 and %d\n",
> > MAX_PKT_BURST);
> > 
> > I am unconvinced, but if you think strongly for this, I won't debate more.
> > 
> >   
> 
> Yes it is close, and I don't have strong opinion on this,
> 
> But existing message says "PMD does not recommend a burst size.", I
> think this may be confusing for user.
> 
> If I see that message I would either debug relevant driver code or
> communicate with driver maintainer for it. But that is not the case,
> just failed to get recommended burst size and problem is in testpmd.
> 
> Anyway, my concern is existing message can be misleading for user.

Maybe shorter:
 	"PMD does not provide required burst size\n"

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 4/4] app/testpmd: enhance getopt_long usage
  2024-03-12 17:03   ` Ferruh Yigit
@ 2024-03-13 16:51     ` David Marchand
  2024-03-13 17:20       ` David Marchand
  2024-03-13 23:28       ` Ferruh Yigit
  0 siblings, 2 replies; 35+ messages in thread
From: David Marchand @ 2024-03-13 16:51 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: dev, Aman Singh, Yuying Zhang

On Tue, Mar 12, 2024 at 6:03 PM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>
> On 3/8/2024 2:48 PM, David Marchand wrote:
> > This is a cleanup similar to previous ones in EAL and examples.
> > Instead of using strcmp for every long options while getopt_long already
> > did such parsing, rely on getopt_long return value.
> >
> > Note for reviewers: this patch is best reviewed once applied locally and
> > displayed with git show -w.
> >
>
> Thanks for the cleanup, it was needed.

Thanks for the in depth review.

>
>
> > Signed-off-by: David Marchand <david.marchand@redhat.com>
> > ---
> >  app/test-pmd/parameters.c | 1928 +++++++++++++++++++++----------------
> >  1 file changed, 1084 insertions(+), 844 deletions(-)
> >
> > diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
> > index 271f0c995a..58f43cb5a8 100644
> > --- a/app/test-pmd/parameters.c
> > +++ b/app/test-pmd/parameters.c
> > @@ -40,6 +40,346 @@
> >
> >  #include "testpmd.h"
> >
> > +enum {
> > +     /* long options mapped to a short option */
> > +#define TESTPMD_OPT_AUTO_START "auto-start"
> > +     TESTPMD_OPT_AUTO_START_NUM = 'a',
> > +#define TESTPMD_OPT_HELP "help"
> > +     TESTPMD_OPT_HELP_NUM = 'h',
> > +#define TESTPMD_OPT_INTERACTIVE "interactive"
> > +     TESTPMD_OPT_INTERACTIVE_NUM = 'i',
> > +
> > +     /* first long only option value must be >= 256 */
> > +     TESTPMD_OPT_LONG_MIN_NUM = 256,
> >
>
> This is to be able to use all short options, not sure if this requires a
> comment.

Yes, those comments do not help.


>
> <...>
>
> > +};
> > +
> > +static struct option long_options[] = {
> >
>
> Can it be constant?

Yes.


>
> > +     { TESTPMD_OPT_AUTO_START, 0, NULL, TESTPMD_OPT_AUTO_START_NUM },
> >
>
> In original version "auto-start" long version is enabled only if
> 'RTE_LIB_CMDLINE' enabled, not sure why, but not for short version, I
> think there is a confusion.

I guess one reason why the --auto-start option is under
RTE_LIB_CMDLINE is because forwarding is always started when in non
interactive mode.
https://git.dpdk.org/dpdk/tree/app/test-pmd/testpmd.c#n4722

-a is available without RTE_LIB_CMDLINE, but it was probably not intentional.

In both cases, -a / --auto-start are a nop when testpmd is compiled
without RTE_LIB_CMDLINE.
So moving it out of the RTE_LIB_CMDLINE is not an issue.


>
> OK to remove RTE_LIB_CMDLINE requirement for 'auto-start' but perhaps
> better to have it in separate patch, what do you think?

Yes, it is worth a separate patch but see below my next comment about
RTE_LIB_CMDLINE check.

>
>
> > +     { TESTPMD_OPT_HELP, 0, NULL, TESTPMD_OPT_HELP_NUM },
> > +#ifdef RTE_LIB_CMDLINE
> > +     { TESTPMD_OPT_INTERACTIVE, 0, NULL, TESTPMD_OPT_INTERACTIVE_NUM },
> > +     { TESTPMD_OPT_CMDLINE_FILE, 1, NULL, TESTPMD_OPT_CMDLINE_FILE},
> >
>
> What about using 'no_argument' & 'required_argument' instead of '0' &
> '1', but I guess it will make lines too big,

Line length is the reason why I used the 0/1 but your suggestion looks
good to me.


> as flag will be always NULL in this approach, what about defining macros
> for arg and no_arg, like:
> ```
> #define ARG(name) (name), required_argument, NULL, name##_NUM
> #define NOARG(name) (name), no_argument, NULL, name##_NUM
> #define OPTARG(name) (name), optional_argument, NULL, name##_NUM
>
> { NOARG(TESTPMD_OPT_INTERACTIVE) },
> { ARG(TESTPMD_OPT_CMDLINE_FILE) },
> ```

It lgtm.


>
> > +     { TESTPMD_OPT_ETH_PEERS_CONFIGFILE, 1, NULL, TESTPMD_OPT_ETH_PEERS_CONFIGFILE_NUM },
> > +     { TESTPMD_OPT_ETH_PEER, 1, NULL, TESTPMD_OPT_ETH_PEER_NUM },
> >
>
> These long options are within "#ifdef RTE_LIB_CMDLINE" block, I don't
> know why, I guess above two can work without cmdline library.

Looking again at the options list, we have a nice mess in there... I
had not realised.

I think the only options that are conditional to RTE_LIB_CMDLINE should be:
-i, -a, --cmdline-file.

As I wrote above, leaving the -a/--auto-start option parsing out of
RTE_LIB_CMDLINE is not an issue.
So it would only leave -i/--interactive and --cmdline-file under
RTE_LIB_CMDLINE.
The rest can be moved out of RTE_LIB_CMDLINE.

And reading your next comment about RTE_LIB_CMDLINE, I think we are in sync.


>
> <...>
>
> > -
> >       argvopt = argv;
> >
>
> Why 'argvopt' is required, why not use 'argv' directly?

I'll have to double check.


>
> <...>
>
> >  #ifdef RTE_LIB_CMDLINE
> > ...
> > +             case TESTPMD_OPT_ETH_PEER_NUM: {
> > +                     char *port_end;
> >
> > -                             if (rte_ether_unformat_addr(port_end,
> > -                                             &peer_eth_addrs[n]) < 0)
> > -                                     rte_exit(EXIT_FAILURE,
> > -                                              "Invalid ethernet address: %s\n",
> > -                                              port_end);
> > -                             nb_peer_eth_addrs++;
> > -                     }
> > +                     errno = 0;
> > +                     n = strtoul(optarg, &port_end, 10);
> > +                     if (errno != 0 || port_end == optarg || *port_end++ != ',')
> > +                             rte_exit(EXIT_FAILURE,
> > +                                     "Invalid eth-peer: %s", optarg);
> > +                     if (n >= RTE_MAX_ETHPORTS)
> > +                             rte_exit(EXIT_FAILURE,
> > +                                     "eth-peer: port %d >= RTE_MAX_ETHPORTS(%d)\n",
> > +                                     n, RTE_MAX_ETHPORTS);
> > +
> > +                     if (rte_ether_unformat_addr(port_end,
> > +                                     &peer_eth_addrs[n]) < 0)
> > +                             rte_exit(EXIT_FAILURE,
> > +                                     "Invalid ethernet address: %s\n",
> > +                                     port_end);
> > +                     nb_peer_eth_addrs++;
> > +                     break;
> > +             }
> >  #endif
> >
>
> Similar to the 'struct option long_options' comment, I think expect from
> "interactive" & "cmdline-file", rest can be moved out of "#ifdef
> RTE_LIB_CMDLINE" block, but not this patch in different patch.

Yes.


>
> <...>
>
> >               default:
> >                       usage(argv[0]);
> >
>
> It is not shown in the patch, to print the error case it uses:
> `fprintf(stderr, "Invalid option: %s\n", argv[optind]);`
>
> But as far as I can see 'optind' is the next arg to call, so instead it
> should be 'optind - 1'.

Oh, good catch:

$ build-mini/app/dpdk-testpmd -c 3 --no-huge -m 40 -a 0:0.0 --vdev
net_null1 --vdev net_null2 -- -i --garbage
Invalid option: (null)
EAL: Error - exiting with code: 1
  Cause: Command line is incomplete or incorrect

>
>
> And just after while loop, there is "if (optind != argc)" check, I don't
> see when this check will be hit, so it looks useless.

But this part actually looks correct to me.
We could still hit this part with non handled trailing strings:

$ build-mini/app/dpdk-testpmd -c 3 --no-huge -m 40 -a 0:0.0 --vdev
net_null1 --vdev net_null2 -- -i garbage
Invalid parameter: garbage
EAL: Error - exiting with code: 1
  Cause: Command line is incorrect
Port 0 is closed
Port 1 is closed


-- 
David Marchand


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 4/4] app/testpmd: enhance getopt_long usage
  2024-03-13 16:51     ` David Marchand
@ 2024-03-13 17:20       ` David Marchand
  2024-03-13 23:28         ` Ferruh Yigit
  2024-03-13 23:28       ` Ferruh Yigit
  1 sibling, 1 reply; 35+ messages in thread
From: David Marchand @ 2024-03-13 17:20 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: dev, Aman Singh, Yuying Zhang

On Wed, Mar 13, 2024 at 5:51 PM David Marchand
<david.marchand@redhat.com> wrote:
> >
> > > +     { TESTPMD_OPT_ETH_PEERS_CONFIGFILE, 1, NULL, TESTPMD_OPT_ETH_PEERS_CONFIGFILE_NUM },
> > > +     { TESTPMD_OPT_ETH_PEER, 1, NULL, TESTPMD_OPT_ETH_PEER_NUM },
> > >
> >
> > These long options are within "#ifdef RTE_LIB_CMDLINE" block, I don't
> > know why, I guess above two can work without cmdline library.
>
> Looking again at the options list, we have a nice mess in there... I
> had not realised.
>
> I think the only options that are conditional to RTE_LIB_CMDLINE should be:
> -i, -a, --cmdline-file.
>
> As I wrote above, leaving the -a/--auto-start option parsing out of
> RTE_LIB_CMDLINE is not an issue.
> So it would only leave -i/--interactive and --cmdline-file under
> RTE_LIB_CMDLINE.
> The rest can be moved out of RTE_LIB_CMDLINE.
>
> And reading your next comment about RTE_LIB_CMDLINE, I think we are in sync.

Actually, the solution is even simpler... it is not possible to
disable the cmdline library.
testpmd won't compile without it (missing #ifdef RTE_LIB_CMDLINE in
different places).

I'll drop all the #ifdef RTE_LIB_CMDLINE checks in a dedicated patch.


-- 
David Marchand


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 4/4] app/testpmd: enhance getopt_long usage
  2024-03-13 16:51     ` David Marchand
  2024-03-13 17:20       ` David Marchand
@ 2024-03-13 23:28       ` Ferruh Yigit
  1 sibling, 0 replies; 35+ messages in thread
From: Ferruh Yigit @ 2024-03-13 23:28 UTC (permalink / raw)
  To: David Marchand; +Cc: dev, Aman Singh, Yuying Zhang

On 3/13/2024 4:51 PM, David Marchand wrote:

<...>

>>
>> And just after while loop, there is "if (optind != argc)" check, I don't
>> see when this check will be hit, so it looks useless.
> But this part actually looks correct to me.
> We could still hit this part with non handled trailing strings:
> 
> $ build-mini/app/dpdk-testpmd -c 3 --no-huge -m 40 -a 0:0.0 --vdev
> net_null1 --vdev net_null2 -- -i garbage
> Invalid parameter: garbage
> EAL: Error - exiting with code: 1
>   Cause: Command line is incorrect
> Port 0 is closed
> Port 1 is closed
>

OK, I see it is to catch non-option argument and works as expected.

I missed that when 'getopt_long()' returns -1 (EOF), it sets 'optind' to
point first non-option argument in argv, and does this by swapping
elements in argv[] (I wasn't aware 'getopt_long()' does this).


Since testpmd doesn't get any non-option argument, it can be possible to
prefix 'short_options' with '+', (like "+ah"), which modify
'getopt_long()' behavior to stop when first non-option argument seen.

This prevents some unnecessary argument parsing, but it seems this is a
GNU extension, not posix standard, so not sure does it worth this
optimization.


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 4/4] app/testpmd: enhance getopt_long usage
  2024-03-13 17:20       ` David Marchand
@ 2024-03-13 23:28         ` Ferruh Yigit
  0 siblings, 0 replies; 35+ messages in thread
From: Ferruh Yigit @ 2024-03-13 23:28 UTC (permalink / raw)
  To: David Marchand; +Cc: dev, Aman Singh, Yuying Zhang

On 3/13/2024 5:20 PM, David Marchand wrote:
> On Wed, Mar 13, 2024 at 5:51 PM David Marchand
> <david.marchand@redhat.com> wrote:
>>>
>>>> +     { TESTPMD_OPT_ETH_PEERS_CONFIGFILE, 1, NULL, TESTPMD_OPT_ETH_PEERS_CONFIGFILE_NUM },
>>>> +     { TESTPMD_OPT_ETH_PEER, 1, NULL, TESTPMD_OPT_ETH_PEER_NUM },
>>>>
>>>
>>> These long options are within "#ifdef RTE_LIB_CMDLINE" block, I don't
>>> know why, I guess above two can work without cmdline library.
>>
>> Looking again at the options list, we have a nice mess in there... I
>> had not realised.
>>
>> I think the only options that are conditional to RTE_LIB_CMDLINE should be:
>> -i, -a, --cmdline-file.
>>
>> As I wrote above, leaving the -a/--auto-start option parsing out of
>> RTE_LIB_CMDLINE is not an issue.
>> So it would only leave -i/--interactive and --cmdline-file under
>> RTE_LIB_CMDLINE.
>> The rest can be moved out of RTE_LIB_CMDLINE.
>>
>> And reading your next comment about RTE_LIB_CMDLINE, I think we are in sync.
> 
> Actually, the solution is even simpler... it is not possible to
> disable the cmdline library.
> testpmd won't compile without it (missing #ifdef RTE_LIB_CMDLINE in
> different places).
> 
> I'll drop all the #ifdef RTE_LIB_CMDLINE checks in a dedicated patch.
> 
> 

+1 to this simplification.

^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v2 0/6] testpmd options parsing cleanup
  2024-03-08 14:48 [PATCH 0/4] testpmd options parsing cleanup David Marchand
                   ` (3 preceding siblings ...)
  2024-03-08 14:48 ` [PATCH 4/4] app/testpmd: enhance getopt_long usage David Marchand
@ 2024-03-14  9:17 ` David Marchand
  2024-03-14  9:17   ` [PATCH v2 1/6] app/testpmd: fix stats-period option check David Marchand
                     ` (6 more replies)
  4 siblings, 7 replies; 35+ messages in thread
From: David Marchand @ 2024-03-14  9:17 UTC (permalink / raw)
  To: dev

This is a cleanup I had in store for ages but never sent.
The idea is to reuse the conventions from EAL and examples when it
comes to using getopt API.

-- 
David Marchand

Changes since v1:
- following Ferruh review, added 2 more cleanup patches,

David Marchand (6):
  app/testpmd: fix stats-period option check
  app/testpmd: fix burst option parsing
  app/testpmd: fix error message for invalid option
  app/testpmd: enhance queue count check
  app/testpmd: remove dead code for disabling cmdline library
  app/testpmd: enhance getopt_long usage

 app/test-pmd/parameters.c | 1945 +++++++++++++++++++++----------------
 app/test-pmd/testpmd.c    |    8 +-
 2 files changed, 1086 insertions(+), 867 deletions(-)

-- 
2.44.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v2 1/6] app/testpmd: fix stats-period option check
  2024-03-14  9:17 ` [PATCH v2 0/6] testpmd options parsing cleanup David Marchand
@ 2024-03-14  9:17   ` David Marchand
  2024-03-14  9:17   ` [PATCH v2 2/6] app/testpmd: fix burst option parsing David Marchand
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 35+ messages in thread
From: David Marchand @ 2024-03-14  9:17 UTC (permalink / raw)
  To: dev
  Cc: stable, Ferruh Yigit, Aman Singh, Yuying Zhang, Pablo de Lara,
	Jingjing Wu

Rather than silently ignore an invalid value, raise an error for
stats-period user input.

Fixes: cfea1f3048d1 ("app/testpmd: print statistics periodically")
Cc: stable@dpdk.org

Signed-off-by: David Marchand <david.marchand@redhat.com>
Acked-by: Ferruh Yigit <ferruh.yigit@amd.com>
---
 app/test-pmd/parameters.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 11b0cce577..d715750bb8 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -776,7 +776,7 @@ launch_args_parse(int argc, char** argv)
 				n = strtoul(optarg, &end, 10);
 				if ((optarg[0] == '\0') || (end == NULL) ||
 						(*end != '\0'))
-					break;
+					rte_exit(EXIT_FAILURE, "Invalid stats-period value\n");
 
 				stats_period = n;
 				break;
-- 
2.44.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v2 2/6] app/testpmd: fix burst option parsing
  2024-03-14  9:17 ` [PATCH v2 0/6] testpmd options parsing cleanup David Marchand
  2024-03-14  9:17   ` [PATCH v2 1/6] app/testpmd: fix stats-period option check David Marchand
@ 2024-03-14  9:17   ` David Marchand
  2024-03-14  9:22     ` Ferruh Yigit
  2024-03-14  9:17   ` [PATCH v2 3/6] app/testpmd: fix error message for invalid option David Marchand
                     ` (4 subsequent siblings)
  6 siblings, 1 reply; 35+ messages in thread
From: David Marchand @ 2024-03-14  9:17 UTC (permalink / raw)
  To: dev
  Cc: stable, Aman Singh, Yuying Zhang, Bernard Iremonger,
	Andrew Rybchenko, Ivan Ilchenko

rte_eth_dev_info_get() is not supposed to fail for a valid port_id, but
for the theoretical case when it would fail, raise an error rather than
skip subsequent options.

Fixes: 6f51deb903b2 ("app/testpmd: check status of getting ethdev info")
Cc: stable@dpdk.org

Signed-off-by: David Marchand <david.marchand@redhat.com>
---
Changes since v1:
- switched to a dedicated error message,

---
 app/test-pmd/parameters.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index d715750bb8..3414a0d38c 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -1128,7 +1128,9 @@ launch_args_parse(int argc, char** argv)
 								0,
 								&dev_info);
 					if (ret != 0)
-						return;
+						rte_exit(EXIT_FAILURE, "Failed to get driver "
+							"recommended burst size, please provide a "
+							"value between 1 and %d\n", MAX_PKT_BURST);
 
 					rec_nb_pkts = dev_info
 						.default_rxportconf.burst_size;
-- 
2.44.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v2 3/6] app/testpmd: fix error message for invalid option
  2024-03-14  9:17 ` [PATCH v2 0/6] testpmd options parsing cleanup David Marchand
  2024-03-14  9:17   ` [PATCH v2 1/6] app/testpmd: fix stats-period option check David Marchand
  2024-03-14  9:17   ` [PATCH v2 2/6] app/testpmd: fix burst option parsing David Marchand
@ 2024-03-14  9:17   ` David Marchand
  2024-03-14  9:23     ` Ferruh Yigit
  2024-03-14  9:17   ` [PATCH v2 4/6] app/testpmd: enhance queue count check David Marchand
                     ` (3 subsequent siblings)
  6 siblings, 1 reply; 35+ messages in thread
From: David Marchand @ 2024-03-14  9:17 UTC (permalink / raw)
  To: dev; +Cc: stable, Aman Singh, Yuying Zhang, Ferruh Yigit

"""
The variable optind is the index of the next element to be processed in
argv.  The system initializes this value to 1.  The caller can reset it
to 1 to restart scanning of the same argv, or when scanning a new
argument vector.
"""

Hence, if an invalid option is passed through testpmd cmdline, getopt
returns '?' and increments optind to the next index in argv for a
subsequent call.
The message should log the previous index.

Fixes: 8fad2e5ab2c5 ("app/testpmd: report invalid command line parameter")
Cc: stable@dpdk.org

Signed-off-by: David Marchand <david.marchand@redhat.com>
---
 app/test-pmd/parameters.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 3414a0d38c..a4c09e2a2b 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -1497,7 +1497,7 @@ launch_args_parse(int argc, char** argv)
 			break;
 		default:
 			usage(argv[0]);
-			fprintf(stderr, "Invalid option: %s\n", argv[optind]);
+			fprintf(stderr, "Invalid option: %s\n", argv[optind - 1]);
 			rte_exit(EXIT_FAILURE,
 				 "Command line is incomplete or incorrect\n");
 			break;
-- 
2.44.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v2 4/6] app/testpmd: enhance queue count check
  2024-03-14  9:17 ` [PATCH v2 0/6] testpmd options parsing cleanup David Marchand
                     ` (2 preceding siblings ...)
  2024-03-14  9:17   ` [PATCH v2 3/6] app/testpmd: fix error message for invalid option David Marchand
@ 2024-03-14  9:17   ` David Marchand
  2024-03-14  9:23     ` Ferruh Yigit
  2024-03-14  9:17   ` [PATCH v2 5/6] app/testpmd: remove dead code for disabling cmdline library David Marchand
                     ` (2 subsequent siblings)
  6 siblings, 1 reply; 35+ messages in thread
From: David Marchand @ 2024-03-14  9:17 UTC (permalink / raw)
  To: dev; +Cc: Aman Singh, Yuying Zhang

Checking the number of rxq/txq in the middle of option parsing is
confusing.
Besides, a check on nb_rxq / nb_txq check already exists after
option parsing.
Only keep this latter check and make testpmd quit in this case.

Signed-off-by: David Marchand <david.marchand@redhat.com>
---
Changes since v1:
- moved the check and termination out of argument parsing,

---
 app/test-pmd/parameters.c | 4 ----
 app/test-pmd/testpmd.c    | 3 +--
 2 files changed, 1 insertion(+), 6 deletions(-)

diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index a4c09e2a2b..fc5cf3a195 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -1098,10 +1098,6 @@ launch_args_parse(int argc, char** argv)
 						  n + nb_rxq,
 						  get_allowed_max_nb_rxq(&pid));
 			}
-			if (!nb_rxq && !nb_txq) {
-				rte_exit(EXIT_FAILURE, "Either rx or tx queues should "
-						"be non-zero\n");
-			}
 			if (!strcmp(lgopts[opt_idx].name, "hairpin-mode")) {
 				char *end = NULL;
 				unsigned int n;
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 9e4e99e53b..81d905d759 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -4619,8 +4619,7 @@ main(int argc, char** argv)
 	}
 
 	if (!nb_rxq && !nb_txq)
-		fprintf(stderr,
-			"Warning: Either rx or tx queues should be non-zero\n");
+		rte_exit(EXIT_FAILURE, "Either rx or tx queues should be non-zero\n");
 
 	if (nb_rxq > 1 && nb_rxq > nb_txq)
 		fprintf(stderr,
-- 
2.44.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v2 5/6] app/testpmd: remove dead code for disabling cmdline library
  2024-03-14  9:17 ` [PATCH v2 0/6] testpmd options parsing cleanup David Marchand
                     ` (3 preceding siblings ...)
  2024-03-14  9:17   ` [PATCH v2 4/6] app/testpmd: enhance queue count check David Marchand
@ 2024-03-14  9:17   ` David Marchand
  2024-03-14 11:33     ` Ferruh Yigit
  2024-03-14  9:17   ` [PATCH v2 6/6] app/testpmd: enhance getopt_long usage David Marchand
  2024-03-14 12:43   ` [PATCH v2 0/6] testpmd options parsing cleanup Ferruh Yigit
  6 siblings, 1 reply; 35+ messages in thread
From: David Marchand @ 2024-03-14  9:17 UTC (permalink / raw)
  To: dev; +Cc: Aman Singh, Yuying Zhang

The cmdline library is always enabled with meson.
Remove traces of a time when it may have been possible to disable it.

Signed-off-by: David Marchand <david.marchand@redhat.com>
---
 app/test-pmd/parameters.c | 19 +------------------
 app/test-pmd/testpmd.c    |  5 +----
 2 files changed, 2 insertions(+), 22 deletions(-)

diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index fc5cf3a195..a69639b6fb 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -45,10 +45,8 @@ usage(char* progname)
 {
 	printf("\nUsage: %s [EAL options] -- [testpmd options]\n\n",
 	       progname);
-#ifdef RTE_LIB_CMDLINE
 	printf("  --interactive: run in interactive mode.\n");
 	printf("  --cmdline-file: execute cli commands before startup.\n");
-#endif
 	printf("  --auto-start: start forwarding on init "
 	       "[always when non-interactive].\n");
 	printf("  --help: display this message and quit.\n");
@@ -95,12 +93,10 @@ usage(char* progname)
 	printf("  --max-pkt-len=N: set the maximum size of packet to N bytes.\n");
 	printf("  --max-lro-pkt-size=N: set the maximum LRO aggregated packet "
 	       "size to N bytes.\n");
-#ifdef RTE_LIB_CMDLINE
 	printf("  --eth-peers-configfile=name: config file with ethernet addresses "
 	       "of peer ports.\n");
 	printf("  --eth-peer=X,M:M:M:M:M:M: set the MAC address of the X peer "
 	       "port (0 <= X < %d).\n", RTE_MAX_ETHPORTS);
-#endif
 	printf("  --disable-crc-strip: disable CRC stripping by hardware.\n");
 	printf("  --enable-scatter: enable scattered Rx.\n");
 	printf("  --enable-lro: enable large receive offload.\n");
@@ -210,7 +206,6 @@ usage(char* progname)
 	       "    0x01 - hairpin ports loop, 0x00 - hairpin port self\n");
 }
 
-#ifdef RTE_LIB_CMDLINE
 static int
 init_peer_eth_addrs(const char *config_filename)
 {
@@ -240,7 +235,6 @@ init_peer_eth_addrs(const char *config_filename)
 	nb_peer_eth_addrs = (portid_t) i;
 	return 0;
 }
-#endif
 
 /*
  * Parse the coremask given as argument (hexadecimal string) and set
@@ -610,13 +604,11 @@ launch_args_parse(int argc, char** argv)
 
 	static struct option lgopts[] = {
 		{ "help",			0, 0, 0 },
-#ifdef RTE_LIB_CMDLINE
 		{ "interactive",		0, 0, 0 },
 		{ "cmdline-file",		1, 0, 0 },
 		{ "auto-start",			0, 0, 0 },
 		{ "eth-peers-configfile",	1, 0, 0 },
 		{ "eth-peer",			1, 0, 0 },
-#endif
 		{ "tx-first",			0, 0, 0 },
 		{ "stats-period",		1, 0, 0 },
 		{ "display-xstats",		1, 0, 0 },
@@ -725,20 +717,13 @@ launch_args_parse(int argc, char** argv)
 
 	argvopt = argv;
 
-#ifdef RTE_LIB_CMDLINE
-#define SHORTOPTS "i"
-#else
-#define SHORTOPTS ""
-#endif
-	while ((opt = getopt_long(argc, argvopt, SHORTOPTS "ah",
+	while ((opt = getopt_long(argc, argvopt, "iah",
 				 lgopts, &opt_idx)) != EOF) {
 		switch (opt) {
-#ifdef RTE_LIB_CMDLINE
 		case 'i':
 			printf("Interactive-mode selected\n");
 			interactive = 1;
 			break;
-#endif
 		case 'a':
 			printf("Auto-start selected\n");
 			auto_start = 1;
@@ -749,7 +734,6 @@ launch_args_parse(int argc, char** argv)
 				usage(argv[0]);
 				exit(EXIT_SUCCESS);
 			}
-#ifdef RTE_LIB_CMDLINE
 			if (!strcmp(lgopts[opt_idx].name, "interactive")) {
 				printf("Interactive-mode selected\n");
 				interactive = 1;
@@ -817,7 +801,6 @@ launch_args_parse(int argc, char** argv)
 						 port_end);
 				nb_peer_eth_addrs++;
 			}
-#endif
 			if (!strcmp(lgopts[opt_idx].name, "tx-ip")) {
 				struct in_addr in;
 				char *end;
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 81d905d759..70ea257fda 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -4700,7 +4700,6 @@ main(int argc, char** argv)
 	if (record_core_cycles)
 		rte_lcore_register_usage_cb(lcore_usage_callback);
 
-#ifdef RTE_LIB_CMDLINE
 	if (init_cmdline() != 0)
 		rte_exit(EXIT_FAILURE,
 			"Could not initialise cmdline context.\n");
@@ -4714,9 +4713,7 @@ main(int argc, char** argv)
 			start_packet_forwarding(0);
 		}
 		prompt();
-	} else
-#endif
-	{
+	} else {
 		printf("No commandline core given, start packet forwarding\n");
 		start_packet_forwarding(tx_first);
 		if (stats_period != 0) {
-- 
2.44.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v2 6/6] app/testpmd: enhance getopt_long usage
  2024-03-14  9:17 ` [PATCH v2 0/6] testpmd options parsing cleanup David Marchand
                     ` (4 preceding siblings ...)
  2024-03-14  9:17   ` [PATCH v2 5/6] app/testpmd: remove dead code for disabling cmdline library David Marchand
@ 2024-03-14  9:17   ` David Marchand
  2024-03-14 11:43     ` Ferruh Yigit
  2024-03-14 12:43   ` [PATCH v2 0/6] testpmd options parsing cleanup Ferruh Yigit
  6 siblings, 1 reply; 35+ messages in thread
From: David Marchand @ 2024-03-14  9:17 UTC (permalink / raw)
  To: dev; +Cc: Aman Singh, Yuying Zhang

This is a cleanup similar to previous ones in EAL and examples.
Instead of using strcmp for every long options while getopt_long already
did such parsing, rely on getopt_long return value.

Note for reviewers: this patch is best reviewed once applied locally and
displayed with git show -w.

Signed-off-by: David Marchand <david.marchand@redhat.com>
---
Changes since v1:
- removed useless comments in options enum definitions,
- constified long_options,
- added macros to shorten long options array definitions,
- removed unneeded argvopt,

---
 app/test-pmd/parameters.c | 1924 +++++++++++++++++++++----------------
 1 file changed, 1083 insertions(+), 841 deletions(-)

diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index a69639b6fb..c13f7564bf 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -40,6 +40,344 @@
 
 #include "testpmd.h"
 
+enum {
+#define TESTPMD_OPT_AUTO_START "auto-start"
+	TESTPMD_OPT_AUTO_START_NUM = 'a',
+#define TESTPMD_OPT_HELP "help"
+	TESTPMD_OPT_HELP_NUM = 'h',
+#define TESTPMD_OPT_INTERACTIVE "interactive"
+	TESTPMD_OPT_INTERACTIVE_NUM = 'i',
+
+	TESTPMD_OPT_LONG_MIN_NUM = 256,
+#define TESTPMD_OPT_CMDLINE_FILE "cmdline-file"
+	TESTPMD_OPT_CMDLINE_FILE_NUM,
+#define TESTPMD_OPT_ETH_PEERS_CONFIGFILE "eth-peers-configfile"
+	TESTPMD_OPT_ETH_PEERS_CONFIGFILE_NUM,
+#define TESTPMD_OPT_ETH_PEER "eth-peer"
+	TESTPMD_OPT_ETH_PEER_NUM,
+#define TESTPMD_OPT_TX_FIRST "tx-first"
+	TESTPMD_OPT_TX_FIRST_NUM,
+#define TESTPMD_OPT_STATS_PERIOD "stats-period"
+	TESTPMD_OPT_STATS_PERIOD_NUM,
+#define TESTPMD_OPT_DISPLAY_XSTATS "display-xstats"
+	TESTPMD_OPT_DISPLAY_XSTATS_NUM,
+#define TESTPMD_OPT_NB_CORES "nb-cores"
+	TESTPMD_OPT_NB_CORES_NUM,
+#define TESTPMD_OPT_NB_PORTS "nb-ports"
+	TESTPMD_OPT_NB_PORTS_NUM,
+#define TESTPMD_OPT_COREMASK "coremask"
+	TESTPMD_OPT_COREMASK_NUM,
+#define TESTPMD_OPT_PORTMASK "portmask"
+	TESTPMD_OPT_PORTMASK_NUM,
+#define TESTPMD_OPT_PORTLIST "portlist"
+	TESTPMD_OPT_PORTLIST_NUM,
+#define TESTPMD_OPT_NUMA "numa"
+	TESTPMD_OPT_NUMA_NUM,
+#define TESTPMD_OPT_NO_NUMA "no-numa"
+	TESTPMD_OPT_NO_NUMA_NUM,
+#define TESTPMD_OPT_MP_ANON "mp-anon"
+	TESTPMD_OPT_MP_ANON_NUM,
+#define TESTPMD_OPT_PORT_NUMA_CONFIG "port-numa-config"
+	TESTPMD_OPT_PORT_NUMA_CONFIG_NUM,
+#define TESTPMD_OPT_RING_NUMA_CONFIG "ring-numa-config"
+	TESTPMD_OPT_RING_NUMA_CONFIG_NUM,
+#define TESTPMD_OPT_SOCKET_NUM "socket-num"
+	TESTPMD_OPT_SOCKET_NUM_NUM,
+#define TESTPMD_OPT_MBUF_SIZE "mbuf-size"
+	TESTPMD_OPT_MBUF_SIZE_NUM,
+#define TESTPMD_OPT_TOTAL_NUM_MBUFS "total-num-mbufs"
+	TESTPMD_OPT_TOTAL_NUM_MBUFS_NUM,
+#define TESTPMD_OPT_MAX_PKT_LEN "max-pkt-len"
+	TESTPMD_OPT_MAX_PKT_LEN_NUM,
+#define TESTPMD_OPT_MAX_LRO_PKT_SIZE "max-lro-pkt-size"
+	TESTPMD_OPT_MAX_LRO_PKT_SIZE_NUM,
+#define TESTPMD_OPT_LATENCYSTATS "latencystats"
+	TESTPMD_OPT_LATENCYSTATS_NUM,
+#define TESTPMD_OPT_BITRATE_STATS "bitrate-stats"
+	TESTPMD_OPT_BITRATE_STATS_NUM,
+#define TESTPMD_OPT_DISABLE_CRC_STRIP "disable-crc-strip"
+	TESTPMD_OPT_DISABLE_CRC_STRIP_NUM,
+#define TESTPMD_OPT_ENABLE_LRO "enable-lro"
+	TESTPMD_OPT_ENABLE_LRO_NUM,
+#define TESTPMD_OPT_ENABLE_RX_CKSUM "enable-rx-cksum"
+	TESTPMD_OPT_ENABLE_RX_CKSUM_NUM,
+#define TESTPMD_OPT_ENABLE_RX_TIMESTAMP "enable-rx-timestamp"
+	TESTPMD_OPT_ENABLE_RX_TIMESTAMP_NUM,
+#define TESTPMD_OPT_ENABLE_SCATTER "enable-scatter"
+	TESTPMD_OPT_ENABLE_SCATTER_NUM,
+#define TESTPMD_OPT_ENABLE_HW_VLAN "enable-hw-vlan"
+	TESTPMD_OPT_ENABLE_HW_VLAN_NUM,
+#define TESTPMD_OPT_ENABLE_HW_VLAN_FILTER "enable-hw-vlan-filter"
+	TESTPMD_OPT_ENABLE_HW_VLAN_FILTER_NUM,
+#define TESTPMD_OPT_ENABLE_HW_VLAN_STRIP "enable-hw-vlan-strip"
+	TESTPMD_OPT_ENABLE_HW_VLAN_STRIP_NUM,
+#define TESTPMD_OPT_ENABLE_HW_VLAN_EXTEND "enable-hw-vlan-extend"
+	TESTPMD_OPT_ENABLE_HW_VLAN_EXTEND_NUM,
+#define TESTPMD_OPT_ENABLE_HW_QINQ_STRIP "enable-hw-qinq-strip"
+	TESTPMD_OPT_ENABLE_HW_QINQ_STRIP_NUM,
+#define TESTPMD_OPT_ENABLE_DROP_EN "enable-drop-en"
+	TESTPMD_OPT_ENABLE_DROP_EN_NUM,
+#define TESTPMD_OPT_DISABLE_RSS "disable-rss"
+	TESTPMD_OPT_DISABLE_RSS_NUM,
+#define TESTPMD_OPT_PORT_TOPOLOGY "port-topology"
+	TESTPMD_OPT_PORT_TOPOLOGY_NUM,
+#define TESTPMD_OPT_FORWARD_MODE "forward-mode"
+	TESTPMD_OPT_FORWARD_MODE_NUM,
+#define TESTPMD_OPT_RSS_IP "rss-ip"
+	TESTPMD_OPT_RSS_IP_NUM,
+#define TESTPMD_OPT_RSS_UDP "rss-udp"
+	TESTPMD_OPT_RSS_UDP_NUM,
+#define TESTPMD_OPT_RSS_LEVEL_OUTER "rss-level-outer"
+	TESTPMD_OPT_RSS_LEVEL_OUTER_NUM,
+#define TESTPMD_OPT_RSS_LEVEL_INNER "rss-level-inner"
+	TESTPMD_OPT_RSS_LEVEL_INNER_NUM,
+#define TESTPMD_OPT_RXQ "rxq"
+	TESTPMD_OPT_RXQ_NUM,
+#define TESTPMD_OPT_TXQ "txq"
+	TESTPMD_OPT_TXQ_NUM,
+#define TESTPMD_OPT_RXD "rxd"
+	TESTPMD_OPT_RXD_NUM,
+#define TESTPMD_OPT_TXD "txd"
+	TESTPMD_OPT_TXD_NUM,
+#define TESTPMD_OPT_HAIRPINQ "hairpinq"
+	TESTPMD_OPT_HAIRPINQ_NUM,
+#define TESTPMD_OPT_HAIRPIN_MODE "hairpin-mode"
+	TESTPMD_OPT_HAIRPIN_MODE_NUM,
+#define TESTPMD_OPT_BURST "burst"
+	TESTPMD_OPT_BURST_NUM,
+#define TESTPMD_OPT_FLOWGEN_CLONES "flowgen-clones"
+	TESTPMD_OPT_FLOWGEN_CLONES_NUM,
+#define TESTPMD_OPT_FLOWGEN_FLOWS "flowgen-flows"
+	TESTPMD_OPT_FLOWGEN_FLOWS_NUM,
+#define TESTPMD_OPT_MBCACHE "mbcache"
+	TESTPMD_OPT_MBCACHE_NUM,
+#define TESTPMD_OPT_TXPT "txpt"
+	TESTPMD_OPT_TXPT_NUM,
+#define TESTPMD_OPT_TXHT "txht"
+	TESTPMD_OPT_TXHT_NUM,
+#define TESTPMD_OPT_TXWT "txwt"
+	TESTPMD_OPT_TXWT_NUM,
+#define TESTPMD_OPT_TXFREET "txfreet"
+	TESTPMD_OPT_TXFREET_NUM,
+#define TESTPMD_OPT_TXRST "txrst"
+	TESTPMD_OPT_TXRST_NUM,
+#define TESTPMD_OPT_RXPT "rxpt"
+	TESTPMD_OPT_RXPT_NUM,
+#define TESTPMD_OPT_RXHT "rxht"
+	TESTPMD_OPT_RXHT_NUM,
+#define TESTPMD_OPT_RXWT "rxwt"
+	TESTPMD_OPT_RXWT_NUM,
+#define TESTPMD_OPT_RXFREET "rxfreet"
+	TESTPMD_OPT_RXFREET_NUM,
+#define TESTPMD_OPT_NO_FLUSH_RX "no-flush-rx"
+	TESTPMD_OPT_NO_FLUSH_RX_NUM,
+#define TESTPMD_OPT_FLOW_ISOLATE_ALL "flow-isolate-all"
+	TESTPMD_OPT_FLOW_ISOLATE_ALL_NUM,
+#define TESTPMD_OPT_DISABLE_FLOW_FLUSH "disable-flow-flush"
+	TESTPMD_OPT_DISABLE_FLOW_FLUSH_NUM,
+#define TESTPMD_OPT_RXOFFS "rxoffs"
+	TESTPMD_OPT_RXOFFS_NUM,
+#define TESTPMD_OPT_RXPKTS "rxpkts"
+	TESTPMD_OPT_RXPKTS_NUM,
+#define TESTPMD_OPT_RXHDRS "rxhdrs"
+	TESTPMD_OPT_RXHDRS_NUM,
+#define TESTPMD_OPT_TXPKTS "txpkts"
+	TESTPMD_OPT_TXPKTS_NUM,
+#define TESTPMD_OPT_MULTI_RX_MEMPOOL "multi-rx-mempool"
+	TESTPMD_OPT_MULTI_RX_MEMPOOL_NUM,
+#define TESTPMD_OPT_TXONLY_MULTI_FLOW "txonly-multi-flow"
+	TESTPMD_OPT_TXONLY_MULTI_FLOW_NUM,
+#define TESTPMD_OPT_RXQ_SHARE "rxq-share"
+	TESTPMD_OPT_RXQ_SHARE_NUM,
+#define TESTPMD_OPT_ETH_LINK_SPEED "eth-link-speed"
+	TESTPMD_OPT_ETH_LINK_SPEED_NUM,
+#define TESTPMD_OPT_DISABLE_LINK_CHECK "disable-link-check"
+	TESTPMD_OPT_DISABLE_LINK_CHECK_NUM,
+#define TESTPMD_OPT_DISABLE_DEVICE_START "disable-device-start"
+	TESTPMD_OPT_DISABLE_DEVICE_START_NUM,
+#define TESTPMD_OPT_NO_LSC_INTERRUPT "no-lsc-interrupt"
+	TESTPMD_OPT_NO_LSC_INTERRUPT_NUM,
+#define TESTPMD_OPT_NO_RMV_INTERRUPT "no-rmv-interrupt"
+	TESTPMD_OPT_NO_RMV_INTERRUPT_NUM,
+#define TESTPMD_OPT_PRINT_EVENT "print-event"
+	TESTPMD_OPT_PRINT_EVENT_NUM,
+#define TESTPMD_OPT_MASK_EVENT "mask-event"
+	TESTPMD_OPT_MASK_EVENT_NUM,
+#define TESTPMD_OPT_TX_OFFLOADS "tx-offloads"
+	TESTPMD_OPT_TX_OFFLOADS_NUM,
+#define TESTPMD_OPT_RX_OFFLOADS "rx-offloads"
+	TESTPMD_OPT_RX_OFFLOADS_NUM,
+#define TESTPMD_OPT_HOT_PLUG "hot-plug"
+	TESTPMD_OPT_HOT_PLUG_NUM,
+#define TESTPMD_OPT_VXLAN_GPE_PORT "vxlan-gpe-port"
+	TESTPMD_OPT_VXLAN_GPE_PORT_NUM,
+#define TESTPMD_OPT_GENEVE_PARSED_PORT "geneve-parsed-port"
+	TESTPMD_OPT_GENEVE_PARSED_PORT_NUM,
+#define TESTPMD_OPT_MLOCKALL "mlockall"
+	TESTPMD_OPT_MLOCKALL_NUM,
+#define TESTPMD_OPT_NO_MLOCKALL "no-mlockall"
+	TESTPMD_OPT_NO_MLOCKALL_NUM,
+#define TESTPMD_OPT_MP_ALLOC "mp-alloc"
+	TESTPMD_OPT_MP_ALLOC_NUM,
+#define TESTPMD_OPT_TX_IP "tx-ip"
+	TESTPMD_OPT_TX_IP_NUM,
+#define TESTPMD_OPT_TX_UDP "tx-udp"
+	TESTPMD_OPT_TX_UDP_NUM,
+#define TESTPMD_OPT_NOISY_TX_SW_BUFFER_SIZE "noisy-tx-sw-buffer-size"
+	TESTPMD_OPT_NOISY_TX_SW_BUFFER_SIZE_NUM,
+#define TESTPMD_OPT_NOISY_TX_SW_BUFFER_FLUSHTIME "noisy-tx-sw-buffer-flushtime"
+	TESTPMD_OPT_NOISY_TX_SW_BUFFER_FLUSHTIME_NUM,
+#define TESTPMD_OPT_NOISY_LKUP_MEMORY "noisy-lkup-memory"
+	TESTPMD_OPT_NOISY_LKUP_MEMORY_NUM,
+#define TESTPMD_OPT_NOISY_LKUP_NUM_WRITES "noisy-lkup-num-writes"
+	TESTPMD_OPT_NOISY_LKUP_NUM_WRITES_NUM,
+#define TESTPMD_OPT_NOISY_LKUP_NUM_READS "noisy-lkup-num-reads"
+	TESTPMD_OPT_NOISY_LKUP_NUM_READS_NUM,
+#define TESTPMD_OPT_NOISY_LKUP_NUM_READS_WRITES "noisy-lkup-num-reads-writes"
+	TESTPMD_OPT_NOISY_LKUP_NUM_READS_WRITES_NUM,
+#define TESTPMD_OPT_NOISY_FORWARD_MODE "noisy-forward-mode"
+	TESTPMD_OPT_NOISY_FORWARD_MODE_NUM,
+#define TESTPMD_OPT_NO_IOVA_CONTIG "no-iova-contig"
+	TESTPMD_OPT_NO_IOVA_CONTIG_NUM,
+#define TESTPMD_OPT_RX_MQ_MODE "rx-mq-mode"
+	TESTPMD_OPT_RX_MQ_MODE_NUM,
+#define TESTPMD_OPT_RECORD_CORE_CYCLES "record-core-cycles"
+	TESTPMD_OPT_RECORD_CORE_CYCLES_NUM,
+#define TESTPMD_OPT_RECORD_BURST_STATS "record-burst-stats"
+	TESTPMD_OPT_RECORD_BURST_STATS_NUM,
+#define TESTPMD_OPT_NUM_PROCS "num-procs"
+	TESTPMD_OPT_NUM_PROCS_NUM,
+#define TESTPMD_OPT_PROC_ID "proc-id"
+	TESTPMD_OPT_PROC_ID_NUM,
+
+	TESTPMD_OPT_LONG_MAX_NUM
+};
+
+static const char short_options[] = {
+	"a" /* auto-start */
+	"h" /* help */
+	"i" /* interactive */
+};
+
+#define NO_ARG(opt) { opt, no_argument, NULL, opt ## _NUM }
+#define REQUIRED_ARG(opt) { opt, required_argument, NULL, opt ## _NUM }
+#define OPTIONAL_ARG(opt) { opt, optional_argument, NULL, opt ## _NUM }
+static const struct option long_options[] = {
+	NO_ARG(TESTPMD_OPT_AUTO_START),
+	NO_ARG(TESTPMD_OPT_HELP),
+	NO_ARG(TESTPMD_OPT_INTERACTIVE),
+	REQUIRED_ARG(TESTPMD_OPT_CMDLINE_FILE),
+	REQUIRED_ARG(TESTPMD_OPT_ETH_PEERS_CONFIGFILE),
+	REQUIRED_ARG(TESTPMD_OPT_ETH_PEER),
+	NO_ARG(TESTPMD_OPT_TX_FIRST),
+	REQUIRED_ARG(TESTPMD_OPT_STATS_PERIOD),
+	REQUIRED_ARG(TESTPMD_OPT_DISPLAY_XSTATS),
+	REQUIRED_ARG(TESTPMD_OPT_NB_CORES),
+	REQUIRED_ARG(TESTPMD_OPT_NB_PORTS),
+	REQUIRED_ARG(TESTPMD_OPT_COREMASK),
+	REQUIRED_ARG(TESTPMD_OPT_PORTMASK),
+	REQUIRED_ARG(TESTPMD_OPT_PORTLIST),
+	NO_ARG(TESTPMD_OPT_NUMA),
+	NO_ARG(TESTPMD_OPT_NO_NUMA),
+	NO_ARG(TESTPMD_OPT_MP_ANON), /* deprecated */
+	REQUIRED_ARG(TESTPMD_OPT_PORT_NUMA_CONFIG),
+	REQUIRED_ARG(TESTPMD_OPT_RING_NUMA_CONFIG),
+	REQUIRED_ARG(TESTPMD_OPT_SOCKET_NUM),
+	REQUIRED_ARG(TESTPMD_OPT_MBUF_SIZE),
+	REQUIRED_ARG(TESTPMD_OPT_TOTAL_NUM_MBUFS),
+	REQUIRED_ARG(TESTPMD_OPT_MAX_PKT_LEN),
+	REQUIRED_ARG(TESTPMD_OPT_MAX_LRO_PKT_SIZE),
+#ifdef RTE_LIB_LATENCYSTATS
+	REQUIRED_ARG(TESTPMD_OPT_LATENCYSTATS),
+#endif
+#ifdef RTE_LIB_BITRATESTATS
+	REQUIRED_ARG(TESTPMD_OPT_BITRATE_STATS),
+#endif
+	NO_ARG(TESTPMD_OPT_DISABLE_CRC_STRIP),
+	NO_ARG(TESTPMD_OPT_ENABLE_LRO),
+	NO_ARG(TESTPMD_OPT_ENABLE_RX_CKSUM),
+	NO_ARG(TESTPMD_OPT_ENABLE_RX_TIMESTAMP),
+	NO_ARG(TESTPMD_OPT_ENABLE_SCATTER),
+	NO_ARG(TESTPMD_OPT_ENABLE_HW_VLAN),
+	NO_ARG(TESTPMD_OPT_ENABLE_HW_VLAN_FILTER),
+	NO_ARG(TESTPMD_OPT_ENABLE_HW_VLAN_STRIP),
+	NO_ARG(TESTPMD_OPT_ENABLE_HW_VLAN_EXTEND),
+	NO_ARG(TESTPMD_OPT_ENABLE_HW_QINQ_STRIP),
+	NO_ARG(TESTPMD_OPT_ENABLE_DROP_EN),
+	NO_ARG(TESTPMD_OPT_DISABLE_RSS),
+	REQUIRED_ARG(TESTPMD_OPT_PORT_TOPOLOGY),
+	REQUIRED_ARG(TESTPMD_OPT_FORWARD_MODE),
+	NO_ARG(TESTPMD_OPT_RSS_IP),
+	NO_ARG(TESTPMD_OPT_RSS_UDP),
+	NO_ARG(TESTPMD_OPT_RSS_LEVEL_OUTER),
+	NO_ARG(TESTPMD_OPT_RSS_LEVEL_INNER),
+	REQUIRED_ARG(TESTPMD_OPT_RXQ),
+	REQUIRED_ARG(TESTPMD_OPT_TXQ),
+	REQUIRED_ARG(TESTPMD_OPT_RXD),
+	REQUIRED_ARG(TESTPMD_OPT_TXD),
+	REQUIRED_ARG(TESTPMD_OPT_HAIRPINQ),
+	REQUIRED_ARG(TESTPMD_OPT_HAIRPIN_MODE),
+	REQUIRED_ARG(TESTPMD_OPT_BURST),
+	REQUIRED_ARG(TESTPMD_OPT_FLOWGEN_CLONES),
+	REQUIRED_ARG(TESTPMD_OPT_FLOWGEN_FLOWS),
+	REQUIRED_ARG(TESTPMD_OPT_MBCACHE),
+	REQUIRED_ARG(TESTPMD_OPT_TXPT),
+	REQUIRED_ARG(TESTPMD_OPT_TXHT),
+	REQUIRED_ARG(TESTPMD_OPT_TXWT),
+	REQUIRED_ARG(TESTPMD_OPT_TXFREET),
+	REQUIRED_ARG(TESTPMD_OPT_TXRST),
+	REQUIRED_ARG(TESTPMD_OPT_RXPT),
+	REQUIRED_ARG(TESTPMD_OPT_RXHT),
+	REQUIRED_ARG(TESTPMD_OPT_RXWT),
+	REQUIRED_ARG(TESTPMD_OPT_RXFREET),
+	NO_ARG(TESTPMD_OPT_NO_FLUSH_RX),
+	NO_ARG(TESTPMD_OPT_FLOW_ISOLATE_ALL),
+	NO_ARG(TESTPMD_OPT_DISABLE_FLOW_FLUSH),
+	REQUIRED_ARG(TESTPMD_OPT_RXOFFS),
+	REQUIRED_ARG(TESTPMD_OPT_RXPKTS),
+	REQUIRED_ARG(TESTPMD_OPT_RXHDRS),
+	REQUIRED_ARG(TESTPMD_OPT_TXPKTS),
+	NO_ARG(TESTPMD_OPT_MULTI_RX_MEMPOOL),
+	NO_ARG(TESTPMD_OPT_TXONLY_MULTI_FLOW),
+	OPTIONAL_ARG(TESTPMD_OPT_RXQ_SHARE),
+	REQUIRED_ARG(TESTPMD_OPT_ETH_LINK_SPEED),
+	NO_ARG(TESTPMD_OPT_DISABLE_LINK_CHECK),
+	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_PRINT_EVENT),
+	REQUIRED_ARG(TESTPMD_OPT_MASK_EVENT),
+	REQUIRED_ARG(TESTPMD_OPT_TX_OFFLOADS),
+	REQUIRED_ARG(TESTPMD_OPT_RX_OFFLOADS),
+	NO_ARG(TESTPMD_OPT_HOT_PLUG),
+	REQUIRED_ARG(TESTPMD_OPT_VXLAN_GPE_PORT),
+	REQUIRED_ARG(TESTPMD_OPT_GENEVE_PARSED_PORT),
+#ifndef RTE_EXEC_ENV_WINDOWS
+	NO_ARG(TESTPMD_OPT_MLOCKALL),
+	NO_ARG(TESTPMD_OPT_NO_MLOCKALL),
+#endif
+	REQUIRED_ARG(TESTPMD_OPT_MP_ALLOC),
+	REQUIRED_ARG(TESTPMD_OPT_TX_IP),
+	REQUIRED_ARG(TESTPMD_OPT_TX_UDP),
+	REQUIRED_ARG(TESTPMD_OPT_NOISY_TX_SW_BUFFER_SIZE),
+	REQUIRED_ARG(TESTPMD_OPT_NOISY_TX_SW_BUFFER_FLUSHTIME),
+	REQUIRED_ARG(TESTPMD_OPT_NOISY_LKUP_MEMORY),
+	REQUIRED_ARG(TESTPMD_OPT_NOISY_LKUP_NUM_WRITES),
+	REQUIRED_ARG(TESTPMD_OPT_NOISY_LKUP_NUM_READS),
+	REQUIRED_ARG(TESTPMD_OPT_NOISY_LKUP_NUM_READS_WRITES),
+	REQUIRED_ARG(TESTPMD_OPT_NOISY_FORWARD_MODE),
+	NO_ARG(TESTPMD_OPT_NO_IOVA_CONTIG),
+	REQUIRED_ARG(TESTPMD_OPT_RX_MQ_MODE),
+	NO_ARG(TESTPMD_OPT_RECORD_CORE_CYCLES),
+	NO_ARG(TESTPMD_OPT_RECORD_BURST_STATS),
+	REQUIRED_ARG(TESTPMD_OPT_NUM_PROCS),
+	REQUIRED_ARG(TESTPMD_OPT_PROC_ID),
+	{ 0, 0, NULL, 0 }
+};
+#undef NO_ARG
+#undef REQUIRED_ARG
+#undef OPTIONAL_ARG
+
 static void
 usage(char* progname)
 {
@@ -587,11 +925,7 @@ parse_link_speed(int n)
 void
 launch_args_parse(int argc, char** argv)
 {
-#define PARAM_PROC_ID "proc-id"
-#define PARAM_NUM_PROCS "num-procs"
-
 	int n, opt;
-	char **argvopt;
 	int opt_idx;
 	portid_t pid;
 	enum { TX, RX };
@@ -602,123 +936,8 @@ launch_args_parse(int argc, char** argv)
 	uint16_t rec_nb_pkts;
 	int ret;
 
-	static struct option lgopts[] = {
-		{ "help",			0, 0, 0 },
-		{ "interactive",		0, 0, 0 },
-		{ "cmdline-file",		1, 0, 0 },
-		{ "auto-start",			0, 0, 0 },
-		{ "eth-peers-configfile",	1, 0, 0 },
-		{ "eth-peer",			1, 0, 0 },
-		{ "tx-first",			0, 0, 0 },
-		{ "stats-period",		1, 0, 0 },
-		{ "display-xstats",		1, 0, 0 },
-		{ "nb-cores",			1, 0, 0 },
-		{ "nb-ports",			1, 0, 0 },
-		{ "coremask",			1, 0, 0 },
-		{ "portmask",			1, 0, 0 },
-		{ "portlist",			1, 0, 0 },
-		{ "numa",			0, 0, 0 },
-		{ "no-numa",			0, 0, 0 },
-		{ "mp-anon",			0, 0, 0 }, /* deprecated */
-		{ "port-numa-config",           1, 0, 0 },
-		{ "ring-numa-config",           1, 0, 0 },
-		{ "socket-num",			1, 0, 0 },
-		{ "mbuf-size",			1, 0, 0 },
-		{ "total-num-mbufs",		1, 0, 0 },
-		{ "max-pkt-len",		1, 0, 0 },
-		{ "max-lro-pkt-size",		1, 0, 0 },
-#ifdef RTE_LIB_LATENCYSTATS
-		{ "latencystats",               1, 0, 0 },
-#endif
-#ifdef RTE_LIB_BITRATESTATS
-		{ "bitrate-stats",              1, 0, 0 },
-#endif
-		{ "disable-crc-strip",          0, 0, 0 },
-		{ "enable-lro",                 0, 0, 0 },
-		{ "enable-rx-cksum",            0, 0, 0 },
-		{ "enable-rx-timestamp",        0, 0, 0 },
-		{ "enable-scatter",             0, 0, 0 },
-		{ "enable-hw-vlan",             0, 0, 0 },
-		{ "enable-hw-vlan-filter",      0, 0, 0 },
-		{ "enable-hw-vlan-strip",       0, 0, 0 },
-		{ "enable-hw-vlan-extend",      0, 0, 0 },
-		{ "enable-hw-qinq-strip",       0, 0, 0 },
-		{ "enable-drop-en",            0, 0, 0 },
-		{ "disable-rss",                0, 0, 0 },
-		{ "port-topology",              1, 0, 0 },
-		{ "forward-mode",               1, 0, 0 },
-		{ "rss-ip",			0, 0, 0 },
-		{ "rss-udp",			0, 0, 0 },
-		{ "rss-level-outer",		0, 0, 0 },
-		{ "rss-level-inner",		0, 0, 0 },
-		{ "rxq",			1, 0, 0 },
-		{ "txq",			1, 0, 0 },
-		{ "rxd",			1, 0, 0 },
-		{ "txd",			1, 0, 0 },
-		{ "hairpinq",			1, 0, 0 },
-		{ "hairpin-mode",		1, 0, 0 },
-		{ "burst",			1, 0, 0 },
-		{ "flowgen-clones",		1, 0, 0 },
-		{ "flowgen-flows",		1, 0, 0 },
-		{ "mbcache",			1, 0, 0 },
-		{ "txpt",			1, 0, 0 },
-		{ "txht",			1, 0, 0 },
-		{ "txwt",			1, 0, 0 },
-		{ "txfreet",			1, 0, 0 },
-		{ "txrst",			1, 0, 0 },
-		{ "rxpt",			1, 0, 0 },
-		{ "rxht",			1, 0, 0 },
-		{ "rxwt",			1, 0, 0 },
-		{ "rxfreet",                    1, 0, 0 },
-		{ "no-flush-rx",	0, 0, 0 },
-		{ "flow-isolate-all",	        0, 0, 0 },
-		{ "disable-flow-flush",         0, 0, 0 },
-		{ "rxoffs",			1, 0, 0 },
-		{ "rxpkts",			1, 0, 0 },
-		{ "rxhdrs",			1, 0, 0 },
-		{ "txpkts",			1, 0, 0 },
-		{ "multi-rx-mempool",           0, 0, 0 },
-		{ "txonly-multi-flow",		0, 0, 0 },
-		{ "rxq-share",			2, 0, 0 },
-		{ "eth-link-speed",		1, 0, 0 },
-		{ "disable-link-check",		0, 0, 0 },
-		{ "disable-device-start",	0, 0, 0 },
-		{ "no-lsc-interrupt",		0, 0, 0 },
-		{ "no-rmv-interrupt",		0, 0, 0 },
-		{ "print-event",		1, 0, 0 },
-		{ "mask-event",			1, 0, 0 },
-		{ "tx-offloads",		1, 0, 0 },
-		{ "rx-offloads",		1, 0, 0 },
-		{ "hot-plug",			0, 0, 0 },
-		{ "vxlan-gpe-port",		1, 0, 0 },
-		{ "geneve-parsed-port",		1, 0, 0 },
-#ifndef RTE_EXEC_ENV_WINDOWS
-		{ "mlockall",			0, 0, 0 },
-		{ "no-mlockall",		0, 0, 0 },
-#endif
-		{ "mp-alloc",			1, 0, 0 },
-		{ "tx-ip",			1, 0, 0 },
-		{ "tx-udp",			1, 0, 0 },
-		{ "noisy-forward-mode",		1, 0, 0 },
-		{ "noisy-tx-sw-buffer-size",	1, 0, 0 },
-		{ "noisy-tx-sw-buffer-flushtime", 1, 0, 0 },
-		{ "noisy-lkup-memory",		1, 0, 0 },
-		{ "noisy-lkup-num-writes",	1, 0, 0 },
-		{ "noisy-lkup-num-reads",	1, 0, 0 },
-		{ "noisy-lkup-num-reads-writes", 1, 0, 0 },
-		{ "no-iova-contig",             0, 0, 0 },
-		{ "rx-mq-mode",                 1, 0, 0 },
-		{ "record-core-cycles",         0, 0, 0 },
-		{ "record-burst-stats",         0, 0, 0 },
-		{ PARAM_NUM_PROCS,              1, 0, 0 },
-		{ PARAM_PROC_ID,                1, 0, 0 },
-		{ 0, 0, 0, 0 },
-	};
-
-	argvopt = argv;
-
-	while ((opt = getopt_long(argc, argvopt, "iah",
-				 lgopts, &opt_idx)) != EOF) {
+	while ((opt = getopt_long(argc, argv, short_options, long_options,
+			&opt_idx)) != EOF) {
 		switch (opt) {
 		case 'i':
 			printf("Interactive-mode selected\n");
@@ -728,751 +947,774 @@ launch_args_parse(int argc, char** argv)
 			printf("Auto-start selected\n");
 			auto_start = 1;
 			break;
+		case 'h':
+			usage(argv[0]);
+			exit(EXIT_SUCCESS);
+			break;
+		case TESTPMD_OPT_CMDLINE_FILE_NUM:
+			printf("CLI commands to be read from %s\n",
+				optarg);
+			strlcpy(cmdline_filename, optarg,
+				sizeof(cmdline_filename));
+			break;
+		case TESTPMD_OPT_TX_FIRST_NUM:
+			printf("Ports to start sending a burst of "
+				"packets first\n");
+			tx_first = 1;
+			break;
+		case TESTPMD_OPT_STATS_PERIOD_NUM: {
+			char *end = NULL;
+			unsigned int n;
 
-		case 0: /*long options */
-			if (!strcmp(lgopts[opt_idx].name, "help")) {
-				usage(argv[0]);
-				exit(EXIT_SUCCESS);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "interactive")) {
-				printf("Interactive-mode selected\n");
-				interactive = 1;
-			}
-			if (!strcmp(lgopts[opt_idx].name, "cmdline-file")) {
-				printf("CLI commands to be read from %s\n",
-				       optarg);
-				strlcpy(cmdline_filename, optarg,
-					sizeof(cmdline_filename));
-			}
-			if (!strcmp(lgopts[opt_idx].name, "auto-start")) {
-				printf("Auto-start selected\n");
-				auto_start = 1;
-			}
-			if (!strcmp(lgopts[opt_idx].name, "tx-first")) {
-				printf("Ports to start sending a burst of "
-						"packets first\n");
-				tx_first = 1;
-			}
-			if (!strcmp(lgopts[opt_idx].name, "stats-period")) {
-				char *end = NULL;
-				unsigned int n;
-
-				n = strtoul(optarg, &end, 10);
-				if ((optarg[0] == '\0') || (end == NULL) ||
-						(*end != '\0'))
-					rte_exit(EXIT_FAILURE, "Invalid stats-period value\n");
-
-				stats_period = n;
-				break;
-			}
-			if (!strcmp(lgopts[opt_idx].name, "display-xstats")) {
-				char rc;
-
-				rc = parse_xstats_list(optarg, &xstats_display,
-						       &xstats_display_num);
-				if (rc != 0)
-					rte_exit(EXIT_FAILURE,
-						 "Failed to parse display-xstats argument: %d\n",
-						 rc);
-			}
-			if (!strcmp(lgopts[opt_idx].name,
-				    "eth-peers-configfile")) {
-				if (init_peer_eth_addrs(optarg) != 0)
-					rte_exit(EXIT_FAILURE,
-						 "Cannot open logfile\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "eth-peer")) {
-				char *port_end;
-
-				errno = 0;
-				n = strtoul(optarg, &port_end, 10);
-				if (errno != 0 || port_end == optarg || *port_end++ != ',')
-					rte_exit(EXIT_FAILURE,
-						 "Invalid eth-peer: %s", optarg);
-				if (n >= RTE_MAX_ETHPORTS)
-					rte_exit(EXIT_FAILURE,
-						 "eth-peer: port %d >= RTE_MAX_ETHPORTS(%d)\n",
-						 n, RTE_MAX_ETHPORTS);
-
-				if (rte_ether_unformat_addr(port_end,
-						&peer_eth_addrs[n]) < 0)
-					rte_exit(EXIT_FAILURE,
-						 "Invalid ethernet address: %s\n",
-						 port_end);
-				nb_peer_eth_addrs++;
-			}
-			if (!strcmp(lgopts[opt_idx].name, "tx-ip")) {
-				struct in_addr in;
-				char *end;
-
-				end = strchr(optarg, ',');
-				if (end == optarg || !end)
-					rte_exit(EXIT_FAILURE,
-						 "Invalid tx-ip: %s", optarg);
+			n = strtoul(optarg, &end, 10);
+			if ((optarg[0] == '\0') || (end == NULL) ||
+					(*end != '\0'))
+				rte_exit(EXIT_FAILURE, "Invalid stats-period value\n");
 
-				*end++ = 0;
-				if (inet_pton(AF_INET, optarg, &in) == 0)
-					rte_exit(EXIT_FAILURE,
-						 "Invalid source IP address: %s\n",
-						 optarg);
-				tx_ip_src_addr = rte_be_to_cpu_32(in.s_addr);
+			stats_period = n;
+			break;
+		}
+		case TESTPMD_OPT_DISPLAY_XSTATS_NUM: {
+			char rc;
+
+			rc = parse_xstats_list(optarg, &xstats_display,
+				&xstats_display_num);
+			if (rc != 0)
+				rte_exit(EXIT_FAILURE,
+					"Failed to parse display-xstats argument: %d\n",
+					rc);
+			break;
+		}
+		case TESTPMD_OPT_ETH_PEERS_CONFIGFILE_NUM:
+			if (init_peer_eth_addrs(optarg) != 0)
+				rte_exit(EXIT_FAILURE,
+					"Cannot open logfile\n");
+			break;
+		case TESTPMD_OPT_ETH_PEER_NUM: {
+			char *port_end;
 
-				if (inet_pton(AF_INET, end, &in) == 0)
-					rte_exit(EXIT_FAILURE,
-						 "Invalid destination IP address: %s\n",
-						 optarg);
-				tx_ip_dst_addr = rte_be_to_cpu_32(in.s_addr);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "tx-udp")) {
-				char *end = NULL;
-
-				errno = 0;
-				n = strtoul(optarg, &end, 10);
-				if (errno != 0 || end == optarg ||
-				    n > UINT16_MAX ||
-				    !(*end == '\0' || *end == ','))
-					rte_exit(EXIT_FAILURE,
-						 "Invalid UDP port: %s\n",
-						 optarg);
-				tx_udp_src_port = n;
-				if (*end == ',') {
-					char *dst = end + 1;
-
-					n = strtoul(dst, &end, 10);
-					if (errno != 0 || end == dst ||
-					    n > UINT16_MAX || *end)
-						rte_exit(EXIT_FAILURE,
-							 "Invalid destination UDP port: %s\n",
-							 dst);
-					tx_udp_dst_port = n;
-				} else {
-					tx_udp_dst_port = n;
-				}
+			errno = 0;
+			n = strtoul(optarg, &port_end, 10);
+			if (errno != 0 || port_end == optarg || *port_end++ != ',')
+				rte_exit(EXIT_FAILURE,
+					"Invalid eth-peer: %s", optarg);
+			if (n >= RTE_MAX_ETHPORTS)
+				rte_exit(EXIT_FAILURE,
+					"eth-peer: port %d >= RTE_MAX_ETHPORTS(%d)\n",
+					n, RTE_MAX_ETHPORTS);
+
+			if (rte_ether_unformat_addr(port_end,
+					&peer_eth_addrs[n]) < 0)
+				rte_exit(EXIT_FAILURE,
+					"Invalid ethernet address: %s\n",
+					port_end);
+			nb_peer_eth_addrs++;
+			break;
+		}
+		case TESTPMD_OPT_TX_IP_NUM: {
+			struct in_addr in;
+			char *end;
+
+			end = strchr(optarg, ',');
+			if (end == optarg || !end)
+				rte_exit(EXIT_FAILURE,
+					"Invalid tx-ip: %s", optarg);
+
+			*end++ = 0;
+			if (inet_pton(AF_INET, optarg, &in) == 0)
+				rte_exit(EXIT_FAILURE,
+					"Invalid source IP address: %s\n",
+					optarg);
+			tx_ip_src_addr = rte_be_to_cpu_32(in.s_addr);
+
+			if (inet_pton(AF_INET, end, &in) == 0)
+				rte_exit(EXIT_FAILURE,
+					"Invalid destination IP address: %s\n",
+					optarg);
+			tx_ip_dst_addr = rte_be_to_cpu_32(in.s_addr);
+			break;
+		}
+		case TESTPMD_OPT_TX_UDP_NUM: {
+			char *end = NULL;
 
-			}
-			if (!strcmp(lgopts[opt_idx].name, "nb-ports")) {
-				n = atoi(optarg);
-				if (n > 0 && n <= nb_ports)
-					nb_fwd_ports = n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "Invalid port %d\n", n);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "nb-cores")) {
-				n = atoi(optarg);
-				if (n > 0 && n <= nb_lcores)
-					nb_fwd_lcores = (uint8_t) n;
-				else
+			errno = 0;
+			n = strtoul(optarg, &end, 10);
+			if (errno != 0 || end == optarg ||
+					n > UINT16_MAX ||
+					!(*end == '\0' || *end == ','))
+				rte_exit(EXIT_FAILURE,
+					"Invalid UDP port: %s\n",
+					optarg);
+			tx_udp_src_port = n;
+			if (*end == ',') {
+				char *dst = end + 1;
+
+				n = strtoul(dst, &end, 10);
+				if (errno != 0 || end == dst ||
+						n > UINT16_MAX || *end)
 					rte_exit(EXIT_FAILURE,
-						 "nb-cores should be > 0 and <= %d\n",
-						 nb_lcores);
+						"Invalid destination UDP port: %s\n",
+						dst);
+				tx_udp_dst_port = n;
+			} else {
+				tx_udp_dst_port = n;
 			}
-			if (!strcmp(lgopts[opt_idx].name, "coremask"))
-				parse_fwd_coremask(optarg);
-			if (!strcmp(lgopts[opt_idx].name, "portmask"))
-				parse_fwd_portmask(optarg);
-			if (!strcmp(lgopts[opt_idx].name, "portlist"))
-				parse_fwd_portlist(optarg);
-			if (!strcmp(lgopts[opt_idx].name, "no-numa"))
-				numa_support = 0;
-			if (!strcmp(lgopts[opt_idx].name, "numa"))
-				numa_support = 1;
-			if (!strcmp(lgopts[opt_idx].name, "mp-anon")) {
+			break;
+		}
+		case TESTPMD_OPT_NB_PORTS_NUM:
+			n = atoi(optarg);
+			if (n > 0 && n <= nb_ports)
+				nb_fwd_ports = n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"Invalid port %d\n", n);
+			break;
+		case TESTPMD_OPT_NB_CORES_NUM:
+			n = atoi(optarg);
+			if (n > 0 && n <= nb_lcores)
+				nb_fwd_lcores = (uint8_t) n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"nb-cores should be > 0 and <= %d\n",
+					nb_lcores);
+			break;
+		case TESTPMD_OPT_COREMASK_NUM:
+			parse_fwd_coremask(optarg);
+			break;
+		case TESTPMD_OPT_PORTMASK_NUM:
+			parse_fwd_portmask(optarg);
+			break;
+		case TESTPMD_OPT_PORTLIST_NUM:
+			parse_fwd_portlist(optarg);
+			break;
+		case TESTPMD_OPT_NO_NUMA_NUM:
+			numa_support = 0;
+			break;
+		case TESTPMD_OPT_NUMA_NUM:
+			numa_support = 1;
+			break;
+		case TESTPMD_OPT_MP_ANON_NUM:
+			mp_alloc_type = MP_ALLOC_ANON;
+			break;
+		case TESTPMD_OPT_MP_ALLOC_NUM:
+			if (!strcmp(optarg, "native"))
+				mp_alloc_type = MP_ALLOC_NATIVE;
+			else if (!strcmp(optarg, "anon"))
 				mp_alloc_type = MP_ALLOC_ANON;
+			else if (!strcmp(optarg, "xmem"))
+				mp_alloc_type = MP_ALLOC_XMEM;
+			else if (!strcmp(optarg, "xmemhuge"))
+				mp_alloc_type = MP_ALLOC_XMEM_HUGE;
+			else if (!strcmp(optarg, "xbuf"))
+				mp_alloc_type = MP_ALLOC_XBUF;
+			else
+				rte_exit(EXIT_FAILURE,
+					"mp-alloc %s invalid - must be: "
+					"native, anon, xmem or xmemhuge\n",
+					optarg);
+			break;
+		case TESTPMD_OPT_PORT_NUMA_CONFIG_NUM:
+			if (parse_portnuma_config(optarg))
+				rte_exit(EXIT_FAILURE,
+					"invalid port-numa configuration\n");
+			break;
+		case TESTPMD_OPT_RING_NUMA_CONFIG_NUM:
+			if (parse_ringnuma_config(optarg))
+				rte_exit(EXIT_FAILURE,
+					"invalid ring-numa configuration\n");
+			break;
+		case TESTPMD_OPT_SOCKET_NUM_NUM:
+			n = atoi(optarg);
+			if (!new_socket_id((uint8_t)n)) {
+				socket_num = (uint8_t)n;
+			} else {
+				print_invalid_socket_id_error();
+				rte_exit(EXIT_FAILURE,
+					"Invalid socket id");
 			}
-			if (!strcmp(lgopts[opt_idx].name, "mp-alloc")) {
-				if (!strcmp(optarg, "native"))
-					mp_alloc_type = MP_ALLOC_NATIVE;
-				else if (!strcmp(optarg, "anon"))
-					mp_alloc_type = MP_ALLOC_ANON;
-				else if (!strcmp(optarg, "xmem"))
-					mp_alloc_type = MP_ALLOC_XMEM;
-				else if (!strcmp(optarg, "xmemhuge"))
-					mp_alloc_type = MP_ALLOC_XMEM_HUGE;
-				else if (!strcmp(optarg, "xbuf"))
-					mp_alloc_type = MP_ALLOC_XBUF;
-				else
-					rte_exit(EXIT_FAILURE,
-						"mp-alloc %s invalid - must be: "
-						"native, anon, xmem or xmemhuge\n",
-						 optarg);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "port-numa-config")) {
-				if (parse_portnuma_config(optarg))
-					rte_exit(EXIT_FAILURE,
-					   "invalid port-numa configuration\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "ring-numa-config"))
-				if (parse_ringnuma_config(optarg))
-					rte_exit(EXIT_FAILURE,
-					   "invalid ring-numa configuration\n");
-			if (!strcmp(lgopts[opt_idx].name, "socket-num")) {
-				n = atoi(optarg);
-				if (!new_socket_id((uint8_t)n)) {
-					socket_num = (uint8_t)n;
-				} else {
-					print_invalid_socket_id_error();
-					rte_exit(EXIT_FAILURE,
-						"Invalid socket id");
-				}
-			}
-			if (!strcmp(lgopts[opt_idx].name, "mbuf-size")) {
-				unsigned int mb_sz[MAX_SEGS_BUFFER_SPLIT];
-				unsigned int nb_segs, i;
-
-				nb_segs = parse_item_list(optarg, "mbuf-size",
-					MAX_SEGS_BUFFER_SPLIT, mb_sz, 0);
-				if (nb_segs <= 0)
-					rte_exit(EXIT_FAILURE,
-						 "bad mbuf-size\n");
-				for (i = 0; i < nb_segs; i++) {
-					if (mb_sz[i] <= 0 || mb_sz[i] > 0xFFFF)
-						rte_exit(EXIT_FAILURE,
-							 "mbuf-size should be "
-							 "> 0 and < 65536\n");
-					mbuf_data_size[i] = (uint16_t) mb_sz[i];
-				}
-				mbuf_data_size_n = nb_segs;
-			}
-			if (!strcmp(lgopts[opt_idx].name, "total-num-mbufs")) {
-				n = atoi(optarg);
-				if (n > MIN_TOTAL_NUM_MBUFS)
-					param_total_num_mbufs = (unsigned)n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "total-num-mbufs should be > %d\n",
-						 MIN_TOTAL_NUM_MBUFS);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "max-pkt-len")) {
-				n = atoi(optarg);
-				if (n >= RTE_ETHER_MIN_LEN)
-					max_rx_pkt_len = n;
-				else
+			break;
+		case TESTPMD_OPT_MBUF_SIZE_NUM: {
+			unsigned int mb_sz[MAX_SEGS_BUFFER_SPLIT];
+			unsigned int nb_segs, i;
+
+			nb_segs = parse_item_list(optarg, "mbuf-size",
+				MAX_SEGS_BUFFER_SPLIT, mb_sz, 0);
+			if (nb_segs <= 0)
+				rte_exit(EXIT_FAILURE,
+					"bad mbuf-size\n");
+			for (i = 0; i < nb_segs; i++) {
+				if (mb_sz[i] <= 0 || mb_sz[i] > 0xFFFF)
 					rte_exit(EXIT_FAILURE,
-						 "Invalid max-pkt-len=%d - should be > %d\n",
-						 n, RTE_ETHER_MIN_LEN);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "max-lro-pkt-size")) {
-				n = atoi(optarg);
-				rx_mode.max_lro_pkt_size = (uint32_t) n;
+						"mbuf-size should be "
+						"> 0 and < 65536\n");
+				mbuf_data_size[i] = (uint16_t) mb_sz[i];
 			}
+			mbuf_data_size_n = nb_segs;
+			break;
+		}
+		case TESTPMD_OPT_TOTAL_NUM_MBUFS_NUM:
+			n = atoi(optarg);
+			if (n > MIN_TOTAL_NUM_MBUFS)
+				param_total_num_mbufs = (unsigned int)n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"total-num-mbufs should be > %d\n",
+					MIN_TOTAL_NUM_MBUFS);
+			break;
+		case TESTPMD_OPT_MAX_PKT_LEN_NUM:
+			n = atoi(optarg);
+			if (n >= RTE_ETHER_MIN_LEN)
+				max_rx_pkt_len = n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"Invalid max-pkt-len=%d - should be > %d\n",
+					n, RTE_ETHER_MIN_LEN);
+			break;
+		case TESTPMD_OPT_MAX_LRO_PKT_SIZE_NUM:
+			n = atoi(optarg);
+			rx_mode.max_lro_pkt_size = (uint32_t) n;
+			break;
 #ifdef RTE_LIB_LATENCYSTATS
-			if (!strcmp(lgopts[opt_idx].name,
-				    "latencystats")) {
-				n = atoi(optarg);
-				if (n >= 0) {
-					latencystats_lcore_id = (lcoreid_t) n;
-					latencystats_enabled = 1;
-				} else
-					rte_exit(EXIT_FAILURE,
-						 "invalid lcore id %d for latencystats"
-						 " must be >= 0\n", n);
-			}
+		case TESTPMD_OPT_LATENCYSTATS_NUM:
+			n = atoi(optarg);
+			if (n >= 0) {
+				latencystats_lcore_id = (lcoreid_t) n;
+				latencystats_enabled = 1;
+			} else
+				rte_exit(EXIT_FAILURE,
+					"invalid lcore id %d for latencystats"
+					" must be >= 0\n", n);
+
+			break;
 #endif
 #ifdef RTE_LIB_BITRATESTATS
-			if (!strcmp(lgopts[opt_idx].name, "bitrate-stats")) {
-				n = atoi(optarg);
-				if (n >= 0) {
-					bitrate_lcore_id = (lcoreid_t) n;
-					bitrate_enabled = 1;
-				} else
-					rte_exit(EXIT_FAILURE,
-						 "invalid lcore id %d for bitrate stats"
-						 " must be >= 0\n", n);
-			}
+		case TESTPMD_OPT_BITRATE_STATS_NUM:
+			n = atoi(optarg);
+			if (n >= 0) {
+				bitrate_lcore_id = (lcoreid_t) n;
+				bitrate_enabled = 1;
+			} else
+				rte_exit(EXIT_FAILURE,
+					"invalid lcore id %d for bitrate stats"
+					" must be >= 0\n", n);
+			break;
 #endif
-			if (!strcmp(lgopts[opt_idx].name, "disable-crc-strip"))
-				rx_offloads |= RTE_ETH_RX_OFFLOAD_KEEP_CRC;
-			if (!strcmp(lgopts[opt_idx].name, "enable-lro"))
-				rx_offloads |= RTE_ETH_RX_OFFLOAD_TCP_LRO;
-			if (!strcmp(lgopts[opt_idx].name, "enable-scatter"))
-				rx_offloads |= RTE_ETH_RX_OFFLOAD_SCATTER;
-			if (!strcmp(lgopts[opt_idx].name, "enable-rx-cksum"))
-				rx_offloads |= RTE_ETH_RX_OFFLOAD_CHECKSUM;
-			if (!strcmp(lgopts[opt_idx].name,
-					"enable-rx-timestamp"))
-				rx_offloads |= RTE_ETH_RX_OFFLOAD_TIMESTAMP;
-			if (!strcmp(lgopts[opt_idx].name, "enable-hw-vlan"))
-				rx_offloads |= RTE_ETH_RX_OFFLOAD_VLAN;
-
-			if (!strcmp(lgopts[opt_idx].name,
-					"enable-hw-vlan-filter"))
-				rx_offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
-
-			if (!strcmp(lgopts[opt_idx].name,
-					"enable-hw-vlan-strip"))
-				rx_offloads |= RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
-
-			if (!strcmp(lgopts[opt_idx].name,
-					"enable-hw-vlan-extend"))
-				rx_offloads |= RTE_ETH_RX_OFFLOAD_VLAN_EXTEND;
-
-			if (!strcmp(lgopts[opt_idx].name,
-					"enable-hw-qinq-strip"))
-				rx_offloads |= RTE_ETH_RX_OFFLOAD_QINQ_STRIP;
-
-			if (!strcmp(lgopts[opt_idx].name, "enable-drop-en"))
-				rx_drop_en = 1;
-
-			if (!strcmp(lgopts[opt_idx].name, "disable-rss"))
-				rss_hf = 0;
-			if (!strcmp(lgopts[opt_idx].name, "port-topology")) {
-				if (!strcmp(optarg, "paired"))
-					port_topology = PORT_TOPOLOGY_PAIRED;
-				else if (!strcmp(optarg, "chained"))
-					port_topology = PORT_TOPOLOGY_CHAINED;
-				else if (!strcmp(optarg, "loop"))
-					port_topology = PORT_TOPOLOGY_LOOP;
-				else
-					rte_exit(EXIT_FAILURE, "port-topology %s invalid -"
-						 " must be: paired, chained or loop\n",
-						 optarg);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "forward-mode"))
-				set_pkt_forwarding_mode(optarg);
-			if (!strcmp(lgopts[opt_idx].name, "rss-ip"))
-				rss_hf = RTE_ETH_RSS_IP;
-			if (!strcmp(lgopts[opt_idx].name, "rss-udp"))
-				rss_hf = RTE_ETH_RSS_UDP;
-			if (!strcmp(lgopts[opt_idx].name, "rss-level-inner"))
-				rss_hf |= RTE_ETH_RSS_LEVEL_INNERMOST;
-			if (!strcmp(lgopts[opt_idx].name, "rss-level-outer"))
-				rss_hf |= RTE_ETH_RSS_LEVEL_OUTERMOST;
-			if (!strcmp(lgopts[opt_idx].name, "rxq")) {
-				n = atoi(optarg);
-				if (n >= 0 && check_nb_rxq((queueid_t)n) == 0)
-					nb_rxq = (queueid_t) n;
-				else
-					rte_exit(EXIT_FAILURE, "rxq %d invalid - must be"
-						  " >= 0 && <= %u\n", n,
-						  get_allowed_max_nb_rxq(&pid));
-			}
-			if (!strcmp(lgopts[opt_idx].name, "txq")) {
-				n = atoi(optarg);
-				if (n >= 0 && check_nb_txq((queueid_t)n) == 0)
-					nb_txq = (queueid_t) n;
-				else
-					rte_exit(EXIT_FAILURE, "txq %d invalid - must be"
-						  " >= 0 && <= %u\n", n,
-						  get_allowed_max_nb_txq(&pid));
-			}
-			if (!strcmp(lgopts[opt_idx].name, "hairpinq")) {
-				n = atoi(optarg);
-				if (n >= 0 &&
-				    check_nb_hairpinq((queueid_t)n) == 0)
-					nb_hairpinq = (queueid_t) n;
-				else
-					rte_exit(EXIT_FAILURE, "txq %d invalid - must be"
-						  " >= 0 && <= %u\n", n,
-						  get_allowed_max_nb_hairpinq
-						  (&pid));
-				if ((n + nb_txq) < 0 ||
-				    check_nb_txq((queueid_t)(n + nb_txq)) != 0)
-					rte_exit(EXIT_FAILURE, "txq + hairpinq "
-						 "%d invalid - must be"
-						  " >= 0 && <= %u\n",
-						  n + nb_txq,
-						  get_allowed_max_nb_txq(&pid));
-				if ((n + nb_rxq) < 0 ||
-				    check_nb_rxq((queueid_t)(n + nb_rxq)) != 0)
-					rte_exit(EXIT_FAILURE, "rxq + hairpinq "
-						 "%d invalid - must be"
-						  " >= 0 && <= %u\n",
-						  n + nb_rxq,
-						  get_allowed_max_nb_rxq(&pid));
-			}
-			if (!strcmp(lgopts[opt_idx].name, "hairpin-mode")) {
-				char *end = NULL;
-				unsigned int n;
-
-				errno = 0;
-				n = strtoul(optarg, &end, 0);
-				if (errno != 0 || end == optarg)
-					rte_exit(EXIT_FAILURE, "hairpin mode invalid\n");
-				else
-					hairpin_mode = (uint32_t)n;
-			}
-			if (!strcmp(lgopts[opt_idx].name, "burst")) {
-				n = atoi(optarg);
-				if (n == 0) {
-					/* A burst size of zero means that the
-					 * PMD should be queried for
-					 * recommended Rx burst size. Since
-					 * testpmd uses a single size for all
-					 * ports, port 0 is queried for the
-					 * value, on the assumption that all
-					 * ports are of the same NIC model.
-					 */
-					ret = eth_dev_info_get_print_err(
-								0,
-								&dev_info);
-					if (ret != 0)
-						rte_exit(EXIT_FAILURE, "Failed to get driver "
-							"recommended burst size, please provide a "
-							"value between 1 and %d\n", MAX_PKT_BURST);
-
-					rec_nb_pkts = dev_info
-						.default_rxportconf.burst_size;
-
-					if (rec_nb_pkts == 0)
-						rte_exit(EXIT_FAILURE,
-							"PMD does not recommend a burst size. "
-							"Provided value must be between "
-							"1 and %d\n", MAX_PKT_BURST);
-					else if (rec_nb_pkts > MAX_PKT_BURST)
-						rte_exit(EXIT_FAILURE,
-							"PMD recommended burst size of %d"
-							" exceeds maximum value of %d\n",
-							rec_nb_pkts, MAX_PKT_BURST);
-					printf("Using PMD-provided burst value of %d\n",
-						rec_nb_pkts);
-					nb_pkt_per_burst = rec_nb_pkts;
-				} else if (n > MAX_PKT_BURST)
-					rte_exit(EXIT_FAILURE,
-						"burst must be between1 and %d\n",
-						MAX_PKT_BURST);
-				else
-					nb_pkt_per_burst = (uint16_t) n;
-			}
-			if (!strcmp(lgopts[opt_idx].name, "flowgen-clones")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					nb_pkt_flowgen_clones = (uint16_t) n;
-				else
+		case TESTPMD_OPT_DISABLE_CRC_STRIP_NUM:
+			rx_offloads |= RTE_ETH_RX_OFFLOAD_KEEP_CRC;
+			break;
+		case TESTPMD_OPT_ENABLE_LRO_NUM:
+			rx_offloads |= RTE_ETH_RX_OFFLOAD_TCP_LRO;
+			break;
+		case TESTPMD_OPT_ENABLE_SCATTER_NUM:
+			rx_offloads |= RTE_ETH_RX_OFFLOAD_SCATTER;
+			break;
+		case TESTPMD_OPT_ENABLE_RX_CKSUM_NUM:
+			rx_offloads |= RTE_ETH_RX_OFFLOAD_CHECKSUM;
+			break;
+		case TESTPMD_OPT_ENABLE_RX_TIMESTAMP_NUM:
+			rx_offloads |= RTE_ETH_RX_OFFLOAD_TIMESTAMP;
+			break;
+		case TESTPMD_OPT_ENABLE_HW_VLAN_NUM:
+			rx_offloads |= RTE_ETH_RX_OFFLOAD_VLAN;
+			break;
+		case TESTPMD_OPT_ENABLE_HW_VLAN_FILTER_NUM:
+			rx_offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
+			break;
+		case TESTPMD_OPT_ENABLE_HW_VLAN_STRIP_NUM:
+			rx_offloads |= RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
+			break;
+		case TESTPMD_OPT_ENABLE_HW_VLAN_EXTEND_NUM:
+			rx_offloads |= RTE_ETH_RX_OFFLOAD_VLAN_EXTEND;
+			break;
+		case TESTPMD_OPT_ENABLE_HW_QINQ_STRIP_NUM:
+			rx_offloads |= RTE_ETH_RX_OFFLOAD_QINQ_STRIP;
+			break;
+		case TESTPMD_OPT_ENABLE_DROP_EN_NUM:
+			rx_drop_en = 1;
+			break;
+		case TESTPMD_OPT_DISABLE_RSS_NUM:
+			rss_hf = 0;
+			break;
+		case TESTPMD_OPT_PORT_TOPOLOGY_NUM:
+			if (!strcmp(optarg, "paired"))
+				port_topology = PORT_TOPOLOGY_PAIRED;
+			else if (!strcmp(optarg, "chained"))
+				port_topology = PORT_TOPOLOGY_CHAINED;
+			else if (!strcmp(optarg, "loop"))
+				port_topology = PORT_TOPOLOGY_LOOP;
+			else
+				rte_exit(EXIT_FAILURE, "port-topology %s invalid -"
+					" must be: paired, chained or loop\n",
+					optarg);
+			break;
+		case TESTPMD_OPT_FORWARD_MODE_NUM:
+			set_pkt_forwarding_mode(optarg);
+			break;
+		case TESTPMD_OPT_RSS_IP_NUM:
+			rss_hf = RTE_ETH_RSS_IP;
+			break;
+		case TESTPMD_OPT_RSS_UDP_NUM:
+			rss_hf = RTE_ETH_RSS_UDP;
+			break;
+		case TESTPMD_OPT_RSS_LEVEL_INNER_NUM:
+			rss_hf |= RTE_ETH_RSS_LEVEL_INNERMOST;
+			break;
+		case TESTPMD_OPT_RSS_LEVEL_OUTER_NUM:
+			rss_hf |= RTE_ETH_RSS_LEVEL_OUTERMOST;
+			break;
+		case TESTPMD_OPT_RXQ_NUM:
+			n = atoi(optarg);
+			if (n >= 0 && check_nb_rxq((queueid_t)n) == 0)
+				nb_rxq = (queueid_t) n;
+			else
+				rte_exit(EXIT_FAILURE, "rxq %d invalid - must be"
+					" >= 0 && <= %u\n", n,
+					get_allowed_max_nb_rxq(&pid));
+			break;
+		case TESTPMD_OPT_TXQ_NUM:
+			n = atoi(optarg);
+			if (n >= 0 && check_nb_txq((queueid_t)n) == 0)
+				nb_txq = (queueid_t) n;
+			else
+				rte_exit(EXIT_FAILURE, "txq %d invalid - must be"
+					" >= 0 && <= %u\n", n,
+					get_allowed_max_nb_txq(&pid));
+			break;
+		case TESTPMD_OPT_HAIRPINQ_NUM:
+			n = atoi(optarg);
+			if (n >= 0 &&
+					check_nb_hairpinq((queueid_t)n) == 0)
+				nb_hairpinq = (queueid_t) n;
+			else
+				rte_exit(EXIT_FAILURE, "txq %d invalid - must be"
+					" >= 0 && <= %u\n", n,
+					get_allowed_max_nb_hairpinq
+					(&pid));
+			if ((n + nb_txq) < 0 ||
+					check_nb_txq((queueid_t)(n + nb_txq)) != 0)
+				rte_exit(EXIT_FAILURE, "txq + hairpinq "
+					"%d invalid - must be"
+					" >= 0 && <= %u\n",
+					n + nb_txq,
+					get_allowed_max_nb_txq(&pid));
+			if ((n + nb_rxq) < 0 ||
+					check_nb_rxq((queueid_t)(n + nb_rxq)) != 0)
+				rte_exit(EXIT_FAILURE, "rxq + hairpinq "
+					"%d invalid - must be"
+					" >= 0 && <= %u\n",
+					n + nb_rxq,
+					get_allowed_max_nb_rxq(&pid));
+			break;
+		case TESTPMD_OPT_HAIRPIN_MODE_NUM: {
+			char *end = NULL;
+			unsigned int n;
+
+			errno = 0;
+			n = strtoul(optarg, &end, 0);
+			if (errno != 0 || end == optarg)
+				rte_exit(EXIT_FAILURE, "hairpin mode invalid\n");
+			else
+				hairpin_mode = (uint32_t)n;
+			break;
+		}
+		case TESTPMD_OPT_BURST_NUM:
+			n = atoi(optarg);
+			if (n == 0) {
+				/* A burst size of zero means that the
+				 * PMD should be queried for
+				 * recommended Rx burst size. Since
+				 * testpmd uses a single size for all
+				 * ports, port 0 is queried for the
+				 * value, on the assumption that all
+				 * ports are of the same NIC model.
+				 */
+				ret = eth_dev_info_get_print_err(
+					0,
+					&dev_info);
+				if (ret != 0)
+					rte_exit(EXIT_FAILURE, "Failed to get driver "
+						"recommended burst size, please provide a "
+						"value between 1 and %d\n", MAX_PKT_BURST);
+
+				rec_nb_pkts = dev_info
+					.default_rxportconf.burst_size;
+
+				if (rec_nb_pkts == 0)
 					rte_exit(EXIT_FAILURE,
-						 "clones must be >= 0 and <= current burst\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "flowgen-flows")) {
-				n = atoi(optarg);
-				if (n > 0)
-					nb_flows_flowgen = (int) n;
-				else
+						"PMD does not recommend a burst size. "
+						"Provided value must be between "
+						"1 and %d\n", MAX_PKT_BURST);
+				else if (rec_nb_pkts > MAX_PKT_BURST)
 					rte_exit(EXIT_FAILURE,
-						 "flows must be >= 1\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "mbcache")) {
-				n = atoi(optarg);
-				if ((n >= 0) &&
-				    (n <= RTE_MEMPOOL_CACHE_MAX_SIZE))
-					mb_mempool_cache = (uint16_t) n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "mbcache must be >= 0 and <= %d\n",
-						 RTE_MEMPOOL_CACHE_MAX_SIZE);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "txfreet")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					tx_free_thresh = (int16_t)n;
-				else
-					rte_exit(EXIT_FAILURE, "txfreet must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "txrst")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					tx_rs_thresh = (int16_t)n;
-				else
-					rte_exit(EXIT_FAILURE, "txrst must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "rxd")) {
-				n = atoi(optarg);
-				if (n > 0) {
-					if (rx_free_thresh >= n)
-						rte_exit(EXIT_FAILURE,
-							 "rxd must be > "
-							 "rx_free_thresh(%d)\n",
-							 (int)rx_free_thresh);
-					else
-						nb_rxd = (uint16_t) n;
-				} else
+						"PMD recommended burst size of %d"
+						" exceeds maximum value of %d\n",
+						rec_nb_pkts, MAX_PKT_BURST);
+				printf("Using PMD-provided burst value of %d\n",
+					rec_nb_pkts);
+				nb_pkt_per_burst = rec_nb_pkts;
+			} else if (n > MAX_PKT_BURST)
+				rte_exit(EXIT_FAILURE,
+					"burst must be between1 and %d\n",
+					MAX_PKT_BURST);
+			else
+				nb_pkt_per_burst = (uint16_t) n;
+			break;
+		case TESTPMD_OPT_FLOWGEN_CLONES_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				nb_pkt_flowgen_clones = (uint16_t) n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"clones must be >= 0 and <= current burst\n");
+			break;
+		case TESTPMD_OPT_FLOWGEN_FLOWS_NUM:
+			n = atoi(optarg);
+			if (n > 0)
+				nb_flows_flowgen = (int) n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"flows must be >= 1\n");
+			break;
+		case TESTPMD_OPT_MBCACHE_NUM:
+			n = atoi(optarg);
+			if ((n >= 0) &&
+					(n <= RTE_MEMPOOL_CACHE_MAX_SIZE))
+				mb_mempool_cache = (uint16_t) n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"mbcache must be >= 0 and <= %d\n",
+					RTE_MEMPOOL_CACHE_MAX_SIZE);
+			break;
+		case TESTPMD_OPT_TXFREET_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				tx_free_thresh = (int16_t)n;
+			else
+				rte_exit(EXIT_FAILURE, "txfreet must be >= 0\n");
+			break;
+		case TESTPMD_OPT_TXRST_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				tx_rs_thresh = (int16_t)n;
+			else
+				rte_exit(EXIT_FAILURE, "txrst must be >= 0\n");
+			break;
+		case TESTPMD_OPT_RXD_NUM:
+			n = atoi(optarg);
+			if (n > 0) {
+				if (rx_free_thresh >= n)
 					rte_exit(EXIT_FAILURE,
-						 "rxd(%d) invalid - must be > 0\n",
-						 n);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "txd")) {
-				n = atoi(optarg);
-				if (n > 0)
-					nb_txd = (uint16_t) n;
+						"rxd must be > "
+						"rx_free_thresh(%d)\n",
+						(int)rx_free_thresh);
 				else
-					rte_exit(EXIT_FAILURE, "txd must be in > 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "txpt")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					tx_pthresh = (int8_t)n;
-				else
-					rte_exit(EXIT_FAILURE, "txpt must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "txht")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					tx_hthresh = (int8_t)n;
-				else
-					rte_exit(EXIT_FAILURE, "txht must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "txwt")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					tx_wthresh = (int8_t)n;
-				else
-					rte_exit(EXIT_FAILURE, "txwt must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "rxpt")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					rx_pthresh = (int8_t)n;
-				else
-					rte_exit(EXIT_FAILURE, "rxpt must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "rxht")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					rx_hthresh = (int8_t)n;
-				else
-					rte_exit(EXIT_FAILURE, "rxht must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "rxwt")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					rx_wthresh = (int8_t)n;
-				else
-					rte_exit(EXIT_FAILURE, "rxwt must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "rxfreet")) {
+					nb_rxd = (uint16_t) n;
+			} else
+				rte_exit(EXIT_FAILURE,
+					"rxd(%d) invalid - must be > 0\n",
+					n);
+			break;
+		case TESTPMD_OPT_TXD_NUM:
+			n = atoi(optarg);
+			if (n > 0)
+				nb_txd = (uint16_t) n;
+			else
+				rte_exit(EXIT_FAILURE, "txd must be in > 0\n");
+			break;
+		case TESTPMD_OPT_TXPT_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				tx_pthresh = (int8_t)n;
+			else
+				rte_exit(EXIT_FAILURE, "txpt must be >= 0\n");
+			break;
+		case TESTPMD_OPT_TXHT_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				tx_hthresh = (int8_t)n;
+			else
+				rte_exit(EXIT_FAILURE, "txht must be >= 0\n");
+			break;
+		case TESTPMD_OPT_TXWT_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				tx_wthresh = (int8_t)n;
+			else
+				rte_exit(EXIT_FAILURE, "txwt must be >= 0\n");
+			break;
+		case TESTPMD_OPT_RXPT_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				rx_pthresh = (int8_t)n;
+			else
+				rte_exit(EXIT_FAILURE, "rxpt must be >= 0\n");
+			break;
+		case TESTPMD_OPT_RXHT_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				rx_hthresh = (int8_t)n;
+			else
+				rte_exit(EXIT_FAILURE, "rxht must be >= 0\n");
+			break;
+		case TESTPMD_OPT_RXWT_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				rx_wthresh = (int8_t)n;
+			else
+				rte_exit(EXIT_FAILURE, "rxwt must be >= 0\n");
+			break;
+		case TESTPMD_OPT_RXFREET_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				rx_free_thresh = (int16_t)n;
+			else
+				rte_exit(EXIT_FAILURE, "rxfreet must be >= 0\n");
+			break;
+		case TESTPMD_OPT_RXOFFS_NUM: {
+			unsigned int seg_off[MAX_SEGS_BUFFER_SPLIT];
+			unsigned int nb_offs;
+
+			nb_offs = parse_item_list
+				(optarg, "rxpkt offsets",
+				MAX_SEGS_BUFFER_SPLIT,
+				seg_off, 0);
+			if (nb_offs > 0)
+				set_rx_pkt_offsets(seg_off, nb_offs);
+			else
+				rte_exit(EXIT_FAILURE, "bad rxoffs\n");
+			break;
+		}
+		case TESTPMD_OPT_RXPKTS_NUM: {
+			unsigned int seg_len[MAX_SEGS_BUFFER_SPLIT];
+			unsigned int nb_segs;
+
+			nb_segs = parse_item_list
+				(optarg, "rxpkt segments",
+				MAX_SEGS_BUFFER_SPLIT,
+				seg_len, 0);
+			if (nb_segs > 0)
+				set_rx_pkt_segments(seg_len, nb_segs);
+			else
+				rte_exit(EXIT_FAILURE, "bad rxpkts\n");
+			break;
+		}
+		case TESTPMD_OPT_RXHDRS_NUM: {
+			unsigned int seg_hdrs[MAX_SEGS_BUFFER_SPLIT];
+			unsigned int nb_segs;
+
+			nb_segs = parse_hdrs_list
+				(optarg, "rxpkt segments",
+				MAX_SEGS_BUFFER_SPLIT,
+				seg_hdrs);
+			if (nb_segs > 0)
+				set_rx_pkt_hdrs(seg_hdrs, nb_segs);
+			else
+				rte_exit(EXIT_FAILURE, "bad rxpkts\n");
+			break;
+		}
+		case TESTPMD_OPT_TXPKTS_NUM: {
+			unsigned int seg_lengths[RTE_MAX_SEGS_PER_PKT];
+			unsigned int nb_segs;
+
+			nb_segs = parse_item_list(optarg, "txpkt segments",
+				RTE_MAX_SEGS_PER_PKT, seg_lengths, 0);
+			if (nb_segs > 0)
+				set_tx_pkt_segments(seg_lengths, nb_segs);
+			else
+				rte_exit(EXIT_FAILURE, "bad txpkts\n");
+			break;
+		}
+		case TESTPMD_OPT_MULTI_RX_MEMPOOL_NUM:
+			multi_rx_mempool = 1;
+			break;
+		case TESTPMD_OPT_TXONLY_MULTI_FLOW_NUM:
+			txonly_multi_flow = 1;
+			break;
+		case TESTPMD_OPT_RXQ_SHARE_NUM:
+			if (optarg == NULL) {
+				rxq_share = UINT32_MAX;
+			} else {
 				n = atoi(optarg);
 				if (n >= 0)
-					rx_free_thresh = (int16_t)n;
-				else
-					rte_exit(EXIT_FAILURE, "rxfreet must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "rxoffs")) {
-				unsigned int seg_off[MAX_SEGS_BUFFER_SPLIT];
-				unsigned int nb_offs;
-
-				nb_offs = parse_item_list
-						(optarg, "rxpkt offsets",
-						 MAX_SEGS_BUFFER_SPLIT,
-						 seg_off, 0);
-				if (nb_offs > 0)
-					set_rx_pkt_offsets(seg_off, nb_offs);
-				else
-					rte_exit(EXIT_FAILURE, "bad rxoffs\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "rxpkts")) {
-				unsigned int seg_len[MAX_SEGS_BUFFER_SPLIT];
-				unsigned int nb_segs;
-				nb_segs = parse_item_list
-						(optarg, "rxpkt segments",
-						 MAX_SEGS_BUFFER_SPLIT,
-						 seg_len, 0);
-				if (nb_segs > 0)
-					set_rx_pkt_segments(seg_len, nb_segs);
-				else
-					rte_exit(EXIT_FAILURE, "bad rxpkts\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "rxhdrs")) {
-				unsigned int seg_hdrs[MAX_SEGS_BUFFER_SPLIT];
-				unsigned int nb_segs;
-
-				nb_segs = parse_hdrs_list
-						(optarg, "rxpkt segments",
-						MAX_SEGS_BUFFER_SPLIT,
-						seg_hdrs);
-				if (nb_segs > 0)
-					set_rx_pkt_hdrs(seg_hdrs, nb_segs);
-				else
-					rte_exit(EXIT_FAILURE, "bad rxpkts\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "txpkts")) {
-				unsigned seg_lengths[RTE_MAX_SEGS_PER_PKT];
-				unsigned int nb_segs;
-
-				nb_segs = parse_item_list(optarg, "txpkt segments",
-						RTE_MAX_SEGS_PER_PKT, seg_lengths, 0);
-				if (nb_segs > 0)
-					set_tx_pkt_segments(seg_lengths, nb_segs);
+					rxq_share = (uint32_t)n;
 				else
-					rte_exit(EXIT_FAILURE, "bad txpkts\n");
+					rte_exit(EXIT_FAILURE, "rxq-share must be >= 0\n");
 			}
-			if (!strcmp(lgopts[opt_idx].name, "multi-rx-mempool"))
-				multi_rx_mempool = 1;
-			if (!strcmp(lgopts[opt_idx].name, "txonly-multi-flow"))
-				txonly_multi_flow = 1;
-			if (!strcmp(lgopts[opt_idx].name, "rxq-share")) {
-				if (optarg == NULL) {
-					rxq_share = UINT32_MAX;
-				} else {
-					n = atoi(optarg);
-					if (n >= 0)
-						rxq_share = (uint32_t)n;
-					else
-						rte_exit(EXIT_FAILURE, "rxq-share must be >= 0\n");
-				}
-			}
-			if (!strcmp(lgopts[opt_idx].name, "no-flush-rx"))
-				no_flush_rx = 1;
-			if (!strcmp(lgopts[opt_idx].name, "eth-link-speed")) {
-				n = atoi(optarg);
-				if (n >= 0 && parse_link_speed(n) > 0)
-					eth_link_speed = parse_link_speed(n);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "disable-link-check"))
-				no_link_check = 1;
-			if (!strcmp(lgopts[opt_idx].name, "disable-device-start"))
-				no_device_start = 1;
-			if (!strcmp(lgopts[opt_idx].name, "no-lsc-interrupt"))
-				lsc_interrupt = 0;
-			if (!strcmp(lgopts[opt_idx].name, "no-rmv-interrupt"))
-				rmv_interrupt = 0;
-			if (!strcmp(lgopts[opt_idx].name, "flow-isolate-all"))
-				flow_isolate_all = 1;
-			if (!strcmp(lgopts[opt_idx].name, "disable-flow-flush"))
-				no_flow_flush = 1;
-			if (!strcmp(lgopts[opt_idx].name, "tx-offloads")) {
-				char *end = NULL;
-				n = strtoull(optarg, &end, 16);
-				if (n >= 0)
-					tx_offloads = (uint64_t)n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "tx-offloads must be >= 0\n");
+			break;
+		case TESTPMD_OPT_NO_FLUSH_RX_NUM:
+			no_flush_rx = 1;
+			break;
+		case TESTPMD_OPT_ETH_LINK_SPEED_NUM:
+			n = atoi(optarg);
+			if (n >= 0 && parse_link_speed(n) > 0)
+				eth_link_speed = parse_link_speed(n);
+			break;
+		case TESTPMD_OPT_DISABLE_LINK_CHECK_NUM:
+			no_link_check = 1;
+			break;
+		case TESTPMD_OPT_DISABLE_DEVICE_START_NUM:
+			no_device_start = 1;
+			break;
+		case TESTPMD_OPT_NO_LSC_INTERRUPT_NUM:
+			lsc_interrupt = 0;
+			break;
+		case TESTPMD_OPT_NO_RMV_INTERRUPT_NUM:
+			rmv_interrupt = 0;
+			break;
+		case TESTPMD_OPT_FLOW_ISOLATE_ALL_NUM:
+			flow_isolate_all = 1;
+			break;
+		case TESTPMD_OPT_DISABLE_FLOW_FLUSH_NUM:
+			no_flow_flush = 1;
+			break;
+		case TESTPMD_OPT_TX_OFFLOADS_NUM: {
+			char *end = NULL;
+
+			n = strtoull(optarg, &end, 16);
+			if (n >= 0)
+				tx_offloads = (uint64_t)n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"tx-offloads must be >= 0\n");
+			break;
+		}
+		case TESTPMD_OPT_RX_OFFLOADS_NUM: {
+			char *end = NULL;
+
+			n = strtoull(optarg, &end, 16);
+			if (n >= 0)
+				rx_offloads = (uint64_t)n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"rx-offloads must be >= 0\n");
+			break;
+		}
+		case TESTPMD_OPT_VXLAN_GPE_PORT_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				vxlan_gpe_udp_port = (uint16_t)n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"vxlan-gpe-port must be >= 0\n");
+			break;
+		case TESTPMD_OPT_GENEVE_PARSED_PORT_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				geneve_udp_port = (uint16_t)n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"geneve-parsed-port must be >= 0\n");
+			break;
+		case TESTPMD_OPT_PRINT_EVENT_NUM:
+			if (parse_event_printing_config(optarg, 1)) {
+				rte_exit(EXIT_FAILURE,
+					"invalid print-event argument\n");
 			}
-
-			if (!strcmp(lgopts[opt_idx].name, "rx-offloads")) {
-				char *end = NULL;
-				n = strtoull(optarg, &end, 16);
-				if (n >= 0)
-					rx_offloads = (uint64_t)n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "rx-offloads must be >= 0\n");
+			break;
+		case TESTPMD_OPT_MASK_EVENT_NUM:
+			if (parse_event_printing_config(optarg, 0)) {
+				rte_exit(EXIT_FAILURE,
+					"invalid mask-event argument\n");
 			}
+			break;
+		case TESTPMD_OPT_HOT_PLUG_NUM:
+			hot_plug = 1;
+			break;
+		case TESTPMD_OPT_MLOCKALL_NUM:
+			do_mlockall = 1;
+			break;
+		case TESTPMD_OPT_NO_MLOCKALL_NUM:
+			do_mlockall = 0;
+			break;
+		case TESTPMD_OPT_NOISY_TX_SW_BUFFER_SIZE_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				noisy_tx_sw_bufsz = n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"noisy-tx-sw-buffer-size must be >= 0\n");
+			break;
+		case TESTPMD_OPT_NOISY_TX_SW_BUFFER_FLUSHTIME_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				noisy_tx_sw_buf_flush_time = n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"noisy-tx-sw-buffer-flushtime must be >= 0\n");
+			break;
+		case TESTPMD_OPT_NOISY_LKUP_MEMORY_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				noisy_lkup_mem_sz = n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"noisy-lkup-memory must be >= 0\n");
+			break;
+		case TESTPMD_OPT_NOISY_LKUP_NUM_WRITES_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				noisy_lkup_num_writes = n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"noisy-lkup-num-writes must be >= 0\n");
+			break;
+		case TESTPMD_OPT_NOISY_LKUP_NUM_READS_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				noisy_lkup_num_reads = n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"noisy-lkup-num-reads must be >= 0\n");
+			break;
+		case TESTPMD_OPT_NOISY_LKUP_NUM_READS_WRITES_NUM:
+			n = atoi(optarg);
+			if (n >= 0)
+				noisy_lkup_num_reads_writes = n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"noisy-lkup-num-reads-writes must be >= 0\n");
+			break;
+		case TESTPMD_OPT_NOISY_FORWARD_MODE_NUM: {
+			unsigned int i;
 
-			if (!strcmp(lgopts[opt_idx].name, "vxlan-gpe-port")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					vxlan_gpe_udp_port = (uint16_t)n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "vxlan-gpe-port must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name,
-				    "geneve-parsed-port")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					geneve_udp_port = (uint16_t)n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "geneve-parsed-port must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name, "print-event"))
-				if (parse_event_printing_config(optarg, 1)) {
-					rte_exit(EXIT_FAILURE,
-						 "invalid print-event argument\n");
-				}
-			if (!strcmp(lgopts[opt_idx].name, "mask-event"))
-				if (parse_event_printing_config(optarg, 0)) {
-					rte_exit(EXIT_FAILURE,
-						 "invalid mask-event argument\n");
+			for (i = 0; i < NOISY_FWD_MODE_MAX; i++) {
+				if (!strcmp(optarg, noisy_fwd_mode_desc[i])) {
+					noisy_fwd_mode = i;
+					break;
 				}
-			if (!strcmp(lgopts[opt_idx].name, "hot-plug"))
-				hot_plug = 1;
-			if (!strcmp(lgopts[opt_idx].name, "mlockall"))
-				do_mlockall = 1;
-			if (!strcmp(lgopts[opt_idx].name, "no-mlockall"))
-				do_mlockall = 0;
-			if (!strcmp(lgopts[opt_idx].name,
-				    "noisy-tx-sw-buffer-size")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					noisy_tx_sw_bufsz = n;
-				else
-					rte_exit(EXIT_FAILURE,
-						"noisy-tx-sw-buffer-size must be >= 0\n");
 			}
-			if (!strcmp(lgopts[opt_idx].name,
-				    "noisy-tx-sw-buffer-flushtime")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					noisy_tx_sw_buf_flush_time = n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "noisy-tx-sw-buffer-flushtime must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name,
-				    "noisy-lkup-memory")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					noisy_lkup_mem_sz = n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "noisy-lkup-memory must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name,
-				    "noisy-lkup-num-writes")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					noisy_lkup_num_writes = n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "noisy-lkup-num-writes must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name,
-				    "noisy-lkup-num-reads")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					noisy_lkup_num_reads = n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "noisy-lkup-num-reads must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name,
-				    "noisy-lkup-num-reads-writes")) {
-				n = atoi(optarg);
-				if (n >= 0)
-					noisy_lkup_num_reads_writes = n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "noisy-lkup-num-reads-writes must be >= 0\n");
-			}
-			if (!strcmp(lgopts[opt_idx].name,
-				    "noisy-forward-mode")) {
-				int i;
-				for (i = 0; i < NOISY_FWD_MODE_MAX; i++)
-					if (!strcmp(optarg, noisy_fwd_mode_desc[i])) {
-						noisy_fwd_mode = i;
-						break;
-					}
-				if (i == NOISY_FWD_MODE_MAX)
-					rte_exit(EXIT_FAILURE, "noisy-forward-mode %s invalid,"
-						 " must be a valid noisy-forward-mode value\n",
-						 optarg);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "no-iova-contig"))
-				mempool_flags = RTE_MEMPOOL_F_NO_IOVA_CONTIG;
-
-			if (!strcmp(lgopts[opt_idx].name, "rx-mq-mode")) {
-				char *end = NULL;
-				n = strtoul(optarg, &end, 16);
-				if (n >= 0 && n <= RTE_ETH_MQ_RX_VMDQ_DCB_RSS)
-					rx_mq_mode = (enum rte_eth_rx_mq_mode)n;
-				else
-					rte_exit(EXIT_FAILURE,
-						 "rx-mq-mode must be >= 0 and <= %d\n",
-						 RTE_ETH_MQ_RX_VMDQ_DCB_RSS);
-			}
-			if (!strcmp(lgopts[opt_idx].name, "record-core-cycles"))
-				record_core_cycles = 1;
-			if (!strcmp(lgopts[opt_idx].name, "record-burst-stats"))
-				record_burst_stats = 1;
-			if (!strcmp(lgopts[opt_idx].name, PARAM_NUM_PROCS))
-				num_procs = atoi(optarg);
-			if (!strcmp(lgopts[opt_idx].name, PARAM_PROC_ID))
-				proc_id = atoi(optarg);
+			if (i == NOISY_FWD_MODE_MAX)
+				rte_exit(EXIT_FAILURE, "noisy-forward-mode %s invalid,"
+					 " must be a valid noisy-forward-mode value\n",
+					 optarg);
 			break;
-		case 'h':
-			usage(argv[0]);
-			exit(EXIT_SUCCESS);
+		}
+		case TESTPMD_OPT_NO_IOVA_CONTIG_NUM:
+			mempool_flags = RTE_MEMPOOL_F_NO_IOVA_CONTIG;
+			break;
+		case TESTPMD_OPT_RX_MQ_MODE_NUM: {
+			char *end = NULL;
+
+			n = strtoul(optarg, &end, 16);
+			if (n >= 0 && n <= RTE_ETH_MQ_RX_VMDQ_DCB_RSS)
+				rx_mq_mode = (enum rte_eth_rx_mq_mode)n;
+			else
+				rte_exit(EXIT_FAILURE,
+					"rx-mq-mode must be >= 0 and <= %d\n",
+					RTE_ETH_MQ_RX_VMDQ_DCB_RSS);
+			break;
+		}
+		case TESTPMD_OPT_RECORD_CORE_CYCLES_NUM:
+			record_core_cycles = 1;
+			break;
+		case TESTPMD_OPT_RECORD_BURST_STATS_NUM:
+			record_burst_stats = 1;
+			break;
+		case TESTPMD_OPT_NUM_PROCS_NUM:
+			num_procs = atoi(optarg);
+			break;
+		case TESTPMD_OPT_PROC_ID_NUM:
+			proc_id = atoi(optarg);
 			break;
 		default:
 			usage(argv[0]);
@@ -1491,9 +1733,9 @@ launch_args_parse(int argc, char** argv)
 
 	if (proc_id >= (int)num_procs)
 		rte_exit(EXIT_FAILURE,
-			 "The multi-process option '%s(%d)' should be less than '%s(%u)'\n",
-			 PARAM_PROC_ID, proc_id,
-			 PARAM_NUM_PROCS, num_procs);
+			"The multi-process option '%s(%d)' should be less than '%s(%u)'\n",
+			TESTPMD_OPT_PROC_ID, proc_id,
+			TESTPMD_OPT_NUM_PROCS, num_procs);
 
 	/* Set offload configuration from command line parameters. */
 	rx_mode.offloads = rx_offloads;
-- 
2.44.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v2 2/6] app/testpmd: fix burst option parsing
  2024-03-14  9:17   ` [PATCH v2 2/6] app/testpmd: fix burst option parsing David Marchand
@ 2024-03-14  9:22     ` Ferruh Yigit
  0 siblings, 0 replies; 35+ messages in thread
From: Ferruh Yigit @ 2024-03-14  9:22 UTC (permalink / raw)
  To: David Marchand, dev
  Cc: stable, Aman Singh, Yuying Zhang, Bernard Iremonger,
	Andrew Rybchenko, Ivan Ilchenko

On 3/14/2024 9:17 AM, David Marchand wrote:
> rte_eth_dev_info_get() is not supposed to fail for a valid port_id, but
> for the theoretical case when it would fail, raise an error rather than
> skip subsequent options.
> 
> Fixes: 6f51deb903b2 ("app/testpmd: check status of getting ethdev info")
> Cc: stable@dpdk.org
> 
> Signed-off-by: David Marchand <david.marchand@redhat.com>
>

Acked-by: Ferruh Yigit <ferruh.yigit@amd.com>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v2 3/6] app/testpmd: fix error message for invalid option
  2024-03-14  9:17   ` [PATCH v2 3/6] app/testpmd: fix error message for invalid option David Marchand
@ 2024-03-14  9:23     ` Ferruh Yigit
  0 siblings, 0 replies; 35+ messages in thread
From: Ferruh Yigit @ 2024-03-14  9:23 UTC (permalink / raw)
  To: David Marchand, dev; +Cc: stable, Aman Singh, Yuying Zhang, Ferruh Yigit

On 3/14/2024 9:17 AM, David Marchand wrote:
> """
> The variable optind is the index of the next element to be processed in
> argv.  The system initializes this value to 1.  The caller can reset it
> to 1 to restart scanning of the same argv, or when scanning a new
> argument vector.
> """
> 
> Hence, if an invalid option is passed through testpmd cmdline, getopt
> returns '?' and increments optind to the next index in argv for a
> subsequent call.
> The message should log the previous index.
> 
> Fixes: 8fad2e5ab2c5 ("app/testpmd: report invalid command line parameter")
> Cc: stable@dpdk.org
> 
> Signed-off-by: David Marchand <david.marchand@redhat.com>
>

Acked-by: Ferruh Yigit <ferruh.yigit@amd.com>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v2 4/6] app/testpmd: enhance queue count check
  2024-03-14  9:17   ` [PATCH v2 4/6] app/testpmd: enhance queue count check David Marchand
@ 2024-03-14  9:23     ` Ferruh Yigit
  0 siblings, 0 replies; 35+ messages in thread
From: Ferruh Yigit @ 2024-03-14  9:23 UTC (permalink / raw)
  To: David Marchand, dev; +Cc: Aman Singh, Yuying Zhang

On 3/14/2024 9:17 AM, David Marchand wrote:
> Checking the number of rxq/txq in the middle of option parsing is
> confusing.
> Besides, a check on nb_rxq / nb_txq check already exists after
> option parsing.
> Only keep this latter check and make testpmd quit in this case.
> 
> Signed-off-by: David Marchand <david.marchand@redhat.com>
>

Acked-by: Ferruh Yigit <ferruh.yigit@amd.com>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v2 5/6] app/testpmd: remove dead code for disabling cmdline library
  2024-03-14  9:17   ` [PATCH v2 5/6] app/testpmd: remove dead code for disabling cmdline library David Marchand
@ 2024-03-14 11:33     ` Ferruh Yigit
  0 siblings, 0 replies; 35+ messages in thread
From: Ferruh Yigit @ 2024-03-14 11:33 UTC (permalink / raw)
  To: David Marchand, dev; +Cc: Aman Singh, Yuying Zhang

On 3/14/2024 9:17 AM, David Marchand wrote:
> The cmdline library is always enabled with meson.
> Remove traces of a time when it may have been possible to disable it.
> 
> Signed-off-by: David Marchand <david.marchand@redhat.com>
>

Acked-by: Ferruh Yigit <ferruh.yigit@amd.com>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v2 6/6] app/testpmd: enhance getopt_long usage
  2024-03-14  9:17   ` [PATCH v2 6/6] app/testpmd: enhance getopt_long usage David Marchand
@ 2024-03-14 11:43     ` Ferruh Yigit
  0 siblings, 0 replies; 35+ messages in thread
From: Ferruh Yigit @ 2024-03-14 11:43 UTC (permalink / raw)
  To: David Marchand, dev; +Cc: Aman Singh, Yuying Zhang

On 3/14/2024 9:17 AM, David Marchand wrote:
> This is a cleanup similar to previous ones in EAL and examples.
> Instead of using strcmp for every long options while getopt_long already
> did such parsing, rely on getopt_long return value.
> 
> Note for reviewers: this patch is best reviewed once applied locally and
> displayed with git show -w.
> 
> Signed-off-by: David Marchand <david.marchand@redhat.com>
>

Acked-by: Ferruh Yigit <ferruh.yigit@amd.com>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v2 0/6] testpmd options parsing cleanup
  2024-03-14  9:17 ` [PATCH v2 0/6] testpmd options parsing cleanup David Marchand
                     ` (5 preceding siblings ...)
  2024-03-14  9:17   ` [PATCH v2 6/6] app/testpmd: enhance getopt_long usage David Marchand
@ 2024-03-14 12:43   ` Ferruh Yigit
  6 siblings, 0 replies; 35+ messages in thread
From: Ferruh Yigit @ 2024-03-14 12:43 UTC (permalink / raw)
  To: David Marchand, dev

On 3/14/2024 9:17 AM, David Marchand wrote:
> This is a cleanup I had in store for ages but never sent.
> The idea is to reuse the conventions from EAL and examples when it
> comes to using getopt API.
> 
> 
> Changes since v1:
> - following Ferruh review, added 2 more cleanup patches,
> 
> David Marchand (6):
>   app/testpmd: fix stats-period option check
>   app/testpmd: fix burst option parsing
>   app/testpmd: fix error message for invalid option
>   app/testpmd: enhance queue count check
>   app/testpmd: remove dead code for disabling cmdline library
>   app/testpmd: enhance getopt_long usage
> 

Series applied to dpdk-next-net/main, thanks.

^ permalink raw reply	[flat|nested] 35+ messages in thread

end of thread, other threads:[~2024-03-14 12:43 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-08 14:48 [PATCH 0/4] testpmd options parsing cleanup David Marchand
2024-03-08 14:48 ` [PATCH 1/4] app/testpmd: fix stats-period option check David Marchand
2024-03-12 16:43   ` Ferruh Yigit
2024-03-08 14:48 ` [PATCH 2/4] app/testpmd: fix burst option parsing David Marchand
2024-03-12 16:47   ` Ferruh Yigit
2024-03-13  7:24     ` David Marchand
2024-03-13 10:37       ` Ferruh Yigit
2024-03-13 11:13         ` David Marchand
2024-03-13 12:09           ` Ferruh Yigit
2024-03-13 16:32             ` Stephen Hemminger
2024-03-08 14:48 ` [PATCH 3/4] app/testpmd: check queue count for related options David Marchand
2024-03-12 16:59   ` Ferruh Yigit
2024-03-13  7:37     ` David Marchand
2024-03-13 10:42       ` Ferruh Yigit
2024-03-13 11:10         ` David Marchand
2024-03-13 12:18           ` Ferruh Yigit
2024-03-08 14:48 ` [PATCH 4/4] app/testpmd: enhance getopt_long usage David Marchand
2024-03-12 17:03   ` Ferruh Yigit
2024-03-13 16:51     ` David Marchand
2024-03-13 17:20       ` David Marchand
2024-03-13 23:28         ` Ferruh Yigit
2024-03-13 23:28       ` Ferruh Yigit
2024-03-14  9:17 ` [PATCH v2 0/6] testpmd options parsing cleanup David Marchand
2024-03-14  9:17   ` [PATCH v2 1/6] app/testpmd: fix stats-period option check David Marchand
2024-03-14  9:17   ` [PATCH v2 2/6] app/testpmd: fix burst option parsing David Marchand
2024-03-14  9:22     ` Ferruh Yigit
2024-03-14  9:17   ` [PATCH v2 3/6] app/testpmd: fix error message for invalid option David Marchand
2024-03-14  9:23     ` Ferruh Yigit
2024-03-14  9:17   ` [PATCH v2 4/6] app/testpmd: enhance queue count check David Marchand
2024-03-14  9:23     ` Ferruh Yigit
2024-03-14  9:17   ` [PATCH v2 5/6] app/testpmd: remove dead code for disabling cmdline library David Marchand
2024-03-14 11:33     ` Ferruh Yigit
2024-03-14  9:17   ` [PATCH v2 6/6] app/testpmd: enhance getopt_long usage David Marchand
2024-03-14 11:43     ` Ferruh Yigit
2024-03-14 12:43   ` [PATCH v2 0/6] testpmd options parsing cleanup Ferruh Yigit

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).