DPDK patches and discussions
 help / color / mirror / Atom feed
From: Chengwen Feng <fengchengwen@huawei.com>
To: <dev@dpdk.org>, <thomas@monjalon.net>, <ferruh.yigit@amd.com>,
	<stephen@networkplumber.org>
Cc: <tangkunshan@huawei.com>
Subject: [RFC v2 6/6] examples/dma: replace getopt with argparse
Date: Mon, 4 Dec 2023 07:50:48 +0000	[thread overview]
Message-ID: <20231204075048.894-7-fengchengwen@huawei.com> (raw)
In-Reply-To: <20231204075048.894-1-fengchengwen@huawei.com>

Replace getopt with argparse.

Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
---
 examples/dma/dmafwd.c    | 288 ++++++++++++++++++---------------------
 examples/dma/meson.build |   2 +-
 2 files changed, 131 insertions(+), 159 deletions(-)

diff --git a/examples/dma/dmafwd.c b/examples/dma/dmafwd.c
index f27317a622..950a13f486 100644
--- a/examples/dma/dmafwd.c
+++ b/examples/dma/dmafwd.c
@@ -4,11 +4,11 @@
 
 #include <stdint.h>
 #include <stdlib.h>
-#include <getopt.h>
 #include <signal.h>
 #include <stdbool.h>
 #include <unistd.h>
 
+#include <rte_argparse.h>
 #include <rte_malloc.h>
 #include <rte_ethdev.h>
 #include <rte_dmadev.h>
@@ -18,16 +18,18 @@
 #define MAX_PKT_BURST 32
 #define MEMPOOL_CACHE_SIZE 512
 #define MIN_POOL_SIZE 65536U
-#define CMD_LINE_OPT_MAC_UPDATING "mac-updating"
-#define CMD_LINE_OPT_NO_MAC_UPDATING "no-mac-updating"
-#define CMD_LINE_OPT_PORTMASK "portmask"
-#define CMD_LINE_OPT_NB_QUEUE "nb-queue"
-#define CMD_LINE_OPT_COPY_TYPE "copy-type"
-#define CMD_LINE_OPT_RING_SIZE "ring-size"
-#define CMD_LINE_OPT_BATCH_SIZE "dma-batch-size"
-#define CMD_LINE_OPT_FRAME_SIZE "max-frame-size"
-#define CMD_LINE_OPT_FORCE_COPY_SIZE "force-min-copy-size"
-#define CMD_LINE_OPT_STATS_INTERVAL "stats-interval"
+#define CMD_LINE_OPT_MAC_UPDATING "--mac-updating"
+#define CMD_LINE_OPT_NO_MAC_UPDATING "--no-mac-updating"
+#define CMD_LINE_OPT_PORTMASK "--portmask"
+#define CMD_LINE_OPT_PORTMASK_INDEX 1
+#define CMD_LINE_OPT_NB_QUEUE "--nb-queue"
+#define CMD_LINE_OPT_COPY_TYPE "--copy-type"
+#define CMD_LINE_OPT_COPY_TYPE_INDEX 2
+#define CMD_LINE_OPT_RING_SIZE "--ring-size"
+#define CMD_LINE_OPT_BATCH_SIZE "--dma-batch-size"
+#define CMD_LINE_OPT_FRAME_SIZE "--max-frame-size"
+#define CMD_LINE_OPT_FORCE_COPY_SIZE "--force-min-copy-size"
+#define CMD_LINE_OPT_STATS_INTERVAL "--stats-interval"
 
 /* configurable number of RX/TX ring descriptors */
 #define RX_DEFAULT_RINGSIZE 1024
@@ -84,7 +86,7 @@ typedef enum copy_mode_t {
 static uint32_t dma_enabled_port_mask;
 
 /* number of RX queues per port */
-static uint16_t nb_queues = 1;
+static int nb_queues = 1;
 
 /* MAC updating enabled by default. */
 static int mac_updating = 1;
@@ -95,10 +97,10 @@ static copy_mode_t copy_mode = COPY_MODE_DMA_NUM;
 /* size of descriptor ring for hardware copy mode or
  * rte_ring for software copy mode
  */
-static unsigned short ring_size = 2048;
+static int ring_size = 2048;
 
 /* interval, in seconds, between stats prints */
-static unsigned short stats_interval = 1;
+static int stats_interval = 1;
 /* global mbuf arrays for tracking DMA bufs */
 #define MBUF_RING_SIZE	2048
 #define MBUF_RING_MASK	(MBUF_RING_SIZE - 1)
@@ -118,9 +120,9 @@ static uint16_t nb_txd = TX_DEFAULT_RINGSIZE;
 
 static volatile bool force_quit;
 
-static uint32_t dma_batch_sz = MAX_PKT_BURST;
-static uint32_t max_frame_size;
-static uint32_t force_min_copy_size;
+static int dma_batch_sz = MAX_PKT_BURST;
+static int max_frame_size;
+static int force_min_copy_size;
 
 /* ethernet addresses of ports */
 static struct rte_ether_addr dma_ports_eth_addr[RTE_MAX_ETHPORTS];
@@ -583,26 +585,6 @@ static void start_forwarding_cores(void)
 }
 /* >8 End of starting to process for each lcore. */
 
-/* Display usage */
-static void
-dma_usage(const char *prgname)
-{
-	printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n"
-		"  -b --dma-batch-size: number of requests per DMA batch\n"
-		"  -f --max-frame-size: max frame size\n"
-		"  -m --force-min-copy-size: force a minimum copy length, even for smaller packets\n"
-		"  -p --portmask: hexadecimal bitmask of ports to configure\n"
-		"  -q NQ: number of RX queues per port (default is 1)\n"
-		"  --[no-]mac-updating: Enable or disable MAC addresses updating (enabled by default)\n"
-		"      When enabled:\n"
-		"       - The source MAC address is replaced by the TX port MAC address\n"
-		"       - The destination MAC address is replaced by 02:00:00:00:00:TX_PORT_ID\n"
-		"  -c --copy-type CT: type of copy: sw|hw\n"
-		"  -s --ring-size RS: size of dmadev descriptor ring for hardware copy mode or rte_ring for software copy mode\n"
-		"  -i --stats-interval SI: interval, in seconds, between stats prints (default is 1)\n",
-			prgname);
-}
-
 static int
 dma_parse_portmask(const char *portmask)
 {
@@ -628,142 +610,132 @@ dma_parse_copy_mode(const char *copy_mode)
 	return COPY_MODE_INVALID_NUM;
 }
 
+static int
+dma_parse_args_cb(uint32_t index, const char *value, void *opaque)
+{
+	int port_mask;
+
+	RTE_SET_USED(opaque);
+
+	if (index == CMD_LINE_OPT_PORTMASK_INDEX) {
+		port_mask = dma_parse_portmask(value);
+		if (port_mask & ~dma_enabled_port_mask || port_mask <= 0) {
+			printf("Invalid portmask, %s, suggest 0x%x\n",
+					value, dma_enabled_port_mask);
+			return -1;
+		}
+		dma_enabled_port_mask = port_mask;
+	} else if (index == CMD_LINE_OPT_COPY_TYPE_INDEX) {
+		copy_mode = dma_parse_copy_mode(value);
+		if (copy_mode == COPY_MODE_INVALID_NUM) {
+			printf("Invalid copy type. Use: sw, hw\n");
+			return -1;
+		}
+	} else {
+		printf("Invalid index %u\n", index);
+		return -1;
+	}
+
+	return 0;
+}
+
 /* Parse the argument given in the command line of the application */
 static int
 dma_parse_args(int argc, char **argv, unsigned int nb_ports)
 {
-	static const char short_options[] =
-		"b:"  /* dma batch size */
-		"c:"  /* copy type (sw|hw) */
-		"f:"  /* max frame size */
-		"m:"  /* force min copy size */
-		"p:"  /* portmask */
-		"q:"  /* number of RX queues per port */
-		"s:"  /* ring size */
-		"i:"  /* interval, in seconds, between stats prints */
-		;
-
-	static const struct option lgopts[] = {
-		{CMD_LINE_OPT_MAC_UPDATING, no_argument, &mac_updating, 1},
-		{CMD_LINE_OPT_NO_MAC_UPDATING, no_argument, &mac_updating, 0},
-		{CMD_LINE_OPT_PORTMASK, required_argument, NULL, 'p'},
-		{CMD_LINE_OPT_NB_QUEUE, required_argument, NULL, 'q'},
-		{CMD_LINE_OPT_COPY_TYPE, required_argument, NULL, 'c'},
-		{CMD_LINE_OPT_RING_SIZE, required_argument, NULL, 's'},
-		{CMD_LINE_OPT_BATCH_SIZE, required_argument, NULL, 'b'},
-		{CMD_LINE_OPT_FRAME_SIZE, required_argument, NULL, 'f'},
-		{CMD_LINE_OPT_FORCE_COPY_SIZE, required_argument, NULL, 'm'},
-		{CMD_LINE_OPT_STATS_INTERVAL, required_argument, NULL, 'i'},
-		{NULL, 0, 0, 0}
+	static struct rte_argparse obj = {
+		.prog_name = "dma",
+		.usage = "[EAL options] -- [optional parameters]",
+		.descriptor = NULL,
+		.epilog = NULL,
+		.exit_on_error = false,
+		.callback = dma_parse_args_cb,
+		.opaque = NULL,
+		.args = {
+			{ CMD_LINE_OPT_MAC_UPDATING, NULL, "Enable MAC addresses updating",
+			  &mac_updating, (void *)1,
+			  RTE_ARGPARSE_ARG_NO_VALUE | RTE_ARGPARSE_ARG_VALUE_INT,
+			},
+			{ CMD_LINE_OPT_NO_MAC_UPDATING, NULL, "Disable MAC addresses updating",
+			  &mac_updating, (void *)0,
+			  RTE_ARGPARSE_ARG_NO_VALUE | RTE_ARGPARSE_ARG_VALUE_INT,
+			},
+			{ CMD_LINE_OPT_PORTMASK, "-p", "hexadecimal bitmask of ports to configure",
+			  NULL, (void *)CMD_LINE_OPT_PORTMASK_INDEX,
+			  RTE_ARGPARSE_ARG_REQUIRED_VALUE,
+			},
+			{ CMD_LINE_OPT_NB_QUEUE, "-q", "number of RX queues per port (default is 1)",
+			  &nb_queues, NULL,
+			  RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT,
+			},
+			{ CMD_LINE_OPT_COPY_TYPE, "-c", "type of copy: sw|hw",
+			  NULL, (void *)CMD_LINE_OPT_COPY_TYPE_INDEX,
+			  RTE_ARGPARSE_ARG_REQUIRED_VALUE,
+			},
+			{ CMD_LINE_OPT_RING_SIZE, "-s", "size of dmadev descriptor ring for hardware copy mode or rte_ring for software copy mode",
+			  &ring_size, NULL,
+			  RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT,
+			},
+			{ CMD_LINE_OPT_BATCH_SIZE, "-b", "number of requests per DMA batch",
+			  &dma_batch_sz, NULL,
+			  RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT,
+			},
+			{ CMD_LINE_OPT_FRAME_SIZE, "-f", "max frame size",
+			  &max_frame_size, NULL,
+			  RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT,
+			},
+			{ CMD_LINE_OPT_FORCE_COPY_SIZE, "-m", "force a minimum copy length, even for smaller packets",
+			  &force_min_copy_size, NULL,
+			  RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT,
+			},
+			{ CMD_LINE_OPT_STATS_INTERVAL, "-i", "interval, in seconds, between stats prints (default is 1)",
+			  &stats_interval, NULL,
+			  RTE_ARGPARSE_ARG_REQUIRED_VALUE | RTE_ARGPARSE_ARG_VALUE_INT,
+			},
+		},
 	};
 
 	const unsigned int default_port_mask = (1 << nb_ports) - 1;
-	int opt, ret;
-	char **argvopt;
-	int option_index;
-	char *prgname = argv[0];
+	int ret;
 
 	dma_enabled_port_mask = default_port_mask;
-	argvopt = argv;
-
-	while ((opt = getopt_long(argc, argvopt, short_options,
-			lgopts, &option_index)) != EOF) {
-
-		switch (opt) {
-		case 'b':
-			dma_batch_sz = atoi(optarg);
-			if (dma_batch_sz > MAX_PKT_BURST) {
-				printf("Invalid dma batch size, %s.\n", optarg);
-				dma_usage(prgname);
-				return -1;
-			}
-			break;
-		case 'f':
-			max_frame_size = atoi(optarg);
-			if (max_frame_size > RTE_ETHER_MAX_JUMBO_FRAME_LEN) {
-				printf("Invalid max frame size, %s.\n", optarg);
-				dma_usage(prgname);
-				return -1;
-			}
-			break;
-
-		case 'm':
-			force_min_copy_size = atoi(optarg);
-			break;
-
-		/* portmask */
-		case 'p':
-			dma_enabled_port_mask = dma_parse_portmask(optarg);
-			if (dma_enabled_port_mask & ~default_port_mask ||
-					dma_enabled_port_mask <= 0) {
-				printf("Invalid portmask, %s, suggest 0x%x\n",
-						optarg, default_port_mask);
-				dma_usage(prgname);
-				return -1;
-			}
-			break;
-
-		case 'q':
-			nb_queues = atoi(optarg);
-			if (nb_queues == 0 || nb_queues > MAX_RX_QUEUES_COUNT) {
-				printf("Invalid RX queues number %s. Max %u\n",
-					optarg, MAX_RX_QUEUES_COUNT);
-				dma_usage(prgname);
-				return -1;
-			}
-			break;
-
-		case 'c':
-			copy_mode = dma_parse_copy_mode(optarg);
-			if (copy_mode == COPY_MODE_INVALID_NUM) {
-				printf("Invalid copy type. Use: sw, hw\n");
-				dma_usage(prgname);
-				return -1;
-			}
-			break;
+	ret = rte_argparse_parse(&obj, argc, argv);
+	if (ret != 0)
+		return ret;
 
-		case 's':
-			ring_size = atoi(optarg);
-			if (ring_size == 0) {
-				printf("Invalid ring size, %s.\n", optarg);
-				dma_usage(prgname);
-				return -1;
-			}
-			/* ring_size must be less-than or equal to MBUF_RING_SIZE
-			 * to avoid overwriting bufs
-			 */
-			if (ring_size > MBUF_RING_SIZE) {
-				printf("Max ring_size is %d, setting ring_size to max",
-						MBUF_RING_SIZE);
-				ring_size = MBUF_RING_SIZE;
-			}
-			break;
+	/* check argument's value which parsing by autosave. */
+	if (dma_batch_sz <= 0 || dma_batch_sz > MAX_PKT_BURST) {
+		printf("Invalid dma batch size, %d.\n", dma_batch_sz);
+		return -1;
+	}
 
-		case 'i':
-			stats_interval = atoi(optarg);
-			if (stats_interval == 0) {
-				printf("Invalid stats interval, setting to 1\n");
-				stats_interval = 1;	/* set to default */
-			}
-			break;
+	if (max_frame_size <= 0 || max_frame_size > RTE_ETHER_MAX_JUMBO_FRAME_LEN) {
+		printf("Invalid max frame size, %d.\n", max_frame_size);
+		return -1;
+	}
 
-		/* long options */
-		case 0:
-			break;
+	if (nb_queues <= 0 || nb_queues > MAX_RX_QUEUES_COUNT) {
+		printf("Invalid RX queues number %d. Max %u\n",
+			nb_queues, MAX_RX_QUEUES_COUNT);
+		return -1;
+	}
 
-		default:
-			dma_usage(prgname);
-			return -1;
-		}
+	if (ring_size <= 0) {
+		printf("Invalid ring size, %d.\n", ring_size);
+		return -1;
+	}
+	if (ring_size > MBUF_RING_SIZE) {
+		printf("Max ring_size is %d, setting ring_size to max",
+				MBUF_RING_SIZE);
+		ring_size = MBUF_RING_SIZE;
 	}
 
-	printf("MAC updating %s\n", mac_updating ? "enabled" : "disabled");
-	if (optind >= 0)
-		argv[optind - 1] = prgname;
+	if (stats_interval <= 0) {
+		printf("Invalid stats interval, setting to 1\n");
+		stats_interval = 1;	/* set to default */
+	}
 
-	ret = optind - 1;
-	optind = 1; /* reset getopt lib */
-	return ret;
+	return 0;
 }
 
 /* check link status, return true if at least one port is up */
@@ -1089,7 +1061,7 @@ main(int argc, char **argv)
 		rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n");
 	/* >8 End of allocates mempool to hold the mbufs. */
 
-	if (force_min_copy_size >
+	if ((uint32_t)force_min_copy_size >
 		(uint32_t)(rte_pktmbuf_data_room_size(dma_pktmbuf_pool) -
 			   RTE_PKTMBUF_HEADROOM))
 		rte_exit(EXIT_FAILURE,
diff --git a/examples/dma/meson.build b/examples/dma/meson.build
index 9fdcad660e..124f9476fc 100644
--- a/examples/dma/meson.build
+++ b/examples/dma/meson.build
@@ -8,7 +8,7 @@
 
 allow_experimental_apis = true
 
-deps += ['dmadev']
+deps += ['argparse', 'dmadev']
 
 sources = files(
         'dmafwd.c',
-- 
2.17.1


  parent reply	other threads:[~2023-12-04  7:54 UTC|newest]

Thread overview: 67+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-11-21 12:26 [24.03 RFC] argparse: add argparse library Chengwen Feng
2023-11-21 16:36 ` Stephen Hemminger
2023-11-22  6:28   ` fengchengwen
2023-12-04  7:50 ` [RFC v2 0/6] " Chengwen Feng
2023-12-04  7:50   ` [RFC v2 1/6] argparse: " Chengwen Feng
2023-12-04 17:10     ` Stephen Hemminger
2023-12-05  1:22       ` fengchengwen
2023-12-04  7:50   ` [RFC v2 2/6] argparse: support verify argument config Chengwen Feng
2023-12-04  7:50   ` [RFC v2 3/6] test/argparse: add verify argument config test Chengwen Feng
2023-12-04  7:50   ` [RFC v2 4/6] argparse: support parse parameters Chengwen Feng
2023-12-04  7:50   ` [RFC v2 5/6] test/argparse: add parse parameters test Chengwen Feng
2023-12-04  7:50   ` Chengwen Feng [this message]
2023-12-11  9:50 ` [RFC v3 00/12] add argparse library Chengwen Feng
2023-12-11  9:50   ` [RFC v3 01/12] eal: introduce more macro for bit definition Chengwen Feng
2023-12-11  9:51   ` [RFC v3 02/12] argparse: add argparse library Chengwen Feng
2023-12-11  9:51   ` [RFC v3 03/12] argparse: support verify argument config Chengwen Feng
2023-12-11  9:51   ` [RFC v3 04/12] test/argparse: add verify argument config test Chengwen Feng
2023-12-11  9:51   ` [RFC v3 05/12] argparse: support parse parameters Chengwen Feng
2023-12-11  9:51   ` [RFC v3 06/12] test/argparse: add parse parameters test Chengwen Feng
2023-12-11  9:51   ` [RFC v3 07/12] argparse: provide parsing known type API Chengwen Feng
2023-12-11  9:51   ` [RFC v3 08/12] test/argparse: add parse type test Chengwen Feng
2023-12-11  9:51   ` [RFC v3 09/12] argparse: support parse unsigned base type Chengwen Feng
2023-12-11  9:51   ` [RFC v3 10/12] test/argparse: add parse unsigned base type test Chengwen Feng
2023-12-11  9:51   ` [RFC v3 11/12] argparse: pretty help info Chengwen Feng
2023-12-11  9:51   ` [RFC v3 12/12] examples/dma: replace getopt with argparse Chengwen Feng
2024-01-22  3:57 ` [PATCH 00/12] add argparse library Chengwen Feng
2024-01-22  3:57   ` [PATCH 01/12] eal: introduce more macro for bit definition Chengwen Feng
2024-01-24 13:00     ` Thomas Monjalon
2024-01-22  3:57   ` [PATCH 02/12] argparse: add argparse library Chengwen Feng
2024-01-22  4:54     ` Stephen Hemminger
2024-01-22  6:06       ` fengchengwen
2024-01-24 13:24     ` Thomas Monjalon
2024-01-25  3:44       ` fengchengwen
2024-01-22  3:57   ` [PATCH 03/12] argparse: support verify argument config Chengwen Feng
2024-01-22  3:57   ` [PATCH 04/12] test/argparse: add verify argument config test Chengwen Feng
2024-01-24 13:01     ` Thomas Monjalon
2024-01-22  3:57   ` [PATCH 05/12] argparse: support parse parameters Chengwen Feng
2024-01-22  3:57   ` [PATCH 06/12] test/argparse: add parse parameters test Chengwen Feng
2024-01-22  3:57   ` [PATCH 07/12] argparse: provide parsing known type API Chengwen Feng
2024-01-22  3:57   ` [PATCH 08/12] test/argparse: add parse type test Chengwen Feng
2024-01-22  3:57   ` [PATCH 09/12] argparse: support parse unsigned base type Chengwen Feng
2024-01-22  3:58   ` [PATCH 10/12] test/argparse: add parse unsigned base type test Chengwen Feng
2024-01-22  3:58   ` [PATCH 11/12] argparse: pretty help info Chengwen Feng
2024-01-22  3:58   ` [PATCH 12/12] examples/dma: replace getopt with argparse Chengwen Feng
2024-01-24 13:26     ` Thomas Monjalon
2024-01-24 15:54 ` [24.03 RFC] argparse: add argparse library Stephen Hemminger
2024-01-25  6:31   ` fengchengwen
2024-01-26 16:38     ` Stephen Hemminger
2024-01-25 11:52 ` [PATCH v2 0/8] " Chengwen Feng
2024-01-25 11:52   ` [PATCH v2 1/8] eal: introduce more macro for bit definition Chengwen Feng
2024-01-25 11:52   ` [PATCH v2 2/8] argparse: add argparse library Chengwen Feng
2024-01-25 11:52   ` [PATCH v2 3/8] argparse: support verify argument config Chengwen Feng
2024-01-25 11:52   ` [PATCH v2 4/8] argparse: support parse parameters Chengwen Feng
2024-01-25 11:52   ` [PATCH v2 5/8] argparse: provide parsing known type API Chengwen Feng
2024-01-25 11:52   ` [PATCH v2 6/8] argparse: support parse unsigned base type Chengwen Feng
2024-01-25 11:52   ` [PATCH v2 7/8] argparse: pretty help info Chengwen Feng
2024-01-25 11:52   ` [PATCH v2 8/8] examples/dma: replace getopt with argparse Chengwen Feng
2024-01-26  6:10 ` [PATCH v3 0/8] add argparse library Chengwen Feng
2024-01-26  6:10   ` [PATCH v3 1/8] eal: introduce more macro for bit definition Chengwen Feng
2024-01-26  6:10   ` [PATCH v3 2/8] argparse: add argparse library Chengwen Feng
2024-01-26  6:10   ` [PATCH v3 3/8] argparse: support verify argument config Chengwen Feng
2024-01-26  6:10   ` [PATCH v3 4/8] argparse: support parse parameters Chengwen Feng
2024-01-26  6:10   ` [PATCH v3 5/8] argparse: provide parsing known type API Chengwen Feng
2024-01-26  6:10   ` [PATCH v3 6/8] argparse: support parse unsigned base type Chengwen Feng
2024-01-26  6:10   ` [PATCH v3 7/8] argparse: pretty help info Chengwen Feng
2024-01-26  6:10   ` [PATCH v3 8/8] examples/dma: replace getopt with argparse Chengwen Feng
2024-02-14 16:53   ` [PATCH v3 0/8] add argparse library Thomas Monjalon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231204075048.894-7-fengchengwen@huawei.com \
    --to=fengchengwen@huawei.com \
    --cc=dev@dpdk.org \
    --cc=ferruh.yigit@amd.com \
    --cc=stephen@networkplumber.org \
    --cc=tangkunshan@huawei.com \
    --cc=thomas@monjalon.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).