DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [RFC] app/testpmd: support multi-process
@ 2021-01-08  9:46 Lijun Ou
  2021-01-08 10:28 ` Ferruh Yigit
                   ` (2 more replies)
  0 siblings, 3 replies; 80+ messages in thread
From: Lijun Ou @ 2021-01-08  9:46 UTC (permalink / raw)
  To: ferruh.yigit, wenzhuo.lu, beilei.xing, bernard.iremonger; +Cc: dev

This patch adds multi-process support for testpmd.
The test cmd example as follows:
the primary cmd:
./testpmd -w xxx --file-prefix=xx -l 0-1 -n 2 -- -i\
--rxq=16 --txq=16 --num-procs=2 --proc-id=0
the secondary cmd:
./testpmd -w xxx --file-prefix=xx -l 2-3 -n 2 -- -i\
--rxq=16 --txq=16 --num-procs=2 --proc-id=1

Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
Signed-off-by: Lijun Ou <oulijun@huawei.com>
---
 app/test-pmd/cmdline.c    |   6 ++-
 app/test-pmd/config.c     |   9 +++-
 app/test-pmd/parameters.c |   9 ++++
 app/test-pmd/testpmd.c    | 133 ++++++++++++++++++++++++++++++++--------------
 app/test-pmd/testpmd.h    |   7 +++
 5 files changed, 121 insertions(+), 43 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 2ccbaa0..2237c9f 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -71,8 +71,6 @@
 #include "cmdline_tm.h"
 #include "bpf_cmd.h"
 
-static struct cmdline *testpmd_cl;
-
 static void cmd_reconfig_device_queue(portid_t id, uint8_t dev, uint8_t queue);
 
 /* *** Help command with introduction. *** */
@@ -17115,6 +17113,10 @@ prompt(void)
 	if (testpmd_cl == NULL)
 		return;
 	cmdline_interact(testpmd_cl);
+	if (unlikely(f_quit == 1)) {
+		dup2(testpmd_fd_copy, testpmd_cl->s_in);
+		close(testpmd_fd_copy);
+	}
 	cmdline_stdin_exit(testpmd_cl);
 }
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 3f6c864..1702e0d 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -3100,6 +3100,8 @@ rss_fwd_config_setup(void)
 	queueid_t  rxq;
 	queueid_t  nb_q;
 	streamid_t  sm_id;
+	int start;
+	int end;
 
 	nb_q = nb_rxq;
 	if (nb_q > nb_txq)
@@ -3117,7 +3119,10 @@ rss_fwd_config_setup(void)
 	init_fwd_streams();
 
 	setup_fwd_config_of_each_lcore(&cur_fwd_config);
-	rxp = 0; rxq = 0;
+	start = proc_id * nb_q / num_procs;
+	end = start + nb_q / num_procs;
+	rxp = 0;
+	rxq = start;
 	for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) {
 		struct fwd_stream *fs;
 
@@ -3134,6 +3139,8 @@ rss_fwd_config_setup(void)
 			continue;
 		rxp = 0;
 		rxq++;
+		if (rxq >= end)
+			rxq=start;
 	}
 }
 
diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 414a006..7807afa 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -45,6 +45,8 @@
 #include <rte_flow.h>
 
 #include "testpmd.h"
+#define PARAM_PROC_ID "proc-id"
+#define PARAM_NUM_PROCS "num-procs"
 
 static void
 usage(char* progname)
@@ -603,6 +605,8 @@ launch_args_parse(int argc, char** argv)
 		{ "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 },
 	};
 
@@ -1359,6 +1363,11 @@ launch_args_parse(int argc, char** argv)
 				record_core_cycles = 1;
 			if (!strcmp(lgopts[opt_idx].name, "record-burst-stats"))
 				record_burst_stats = 1;
+
+			if (strncmp(lgopts[opt_idx].name, PARAM_NUM_PROCS, 8) == 0)
+				num_procs = atoi(optarg);
+			if (strncmp(lgopts[opt_idx].name, PARAM_PROC_ID, 7) == 0)
+				proc_id = atoi(optarg);
 			break;
 		case 'h':
 			usage(argv[0]);
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 2b60f6c..7ab5f48 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -63,6 +63,8 @@
 
 #include "testpmd.h"
 
+int testpmd_fd_copy = 500; /* the copy of STDIN_FILENO */
+
 #ifndef MAP_HUGETLB
 /* FreeBSD may not have MAP_HUGETLB (in fact, it probably doesn't) */
 #define HUGE_FLAG (0x40000)
@@ -79,6 +81,7 @@
 
 #define EXTMEM_HEAP_NAME "extmem"
 #define EXTBUF_ZONE_SIZE RTE_PGSIZE_2M
+#define MULTIPLE_PROCESS_HANDLE
 
 uint16_t verbose_level = 0; /**< Silent by default. */
 int testpmd_logtype; /**< Log type for testpmd logs */
@@ -125,6 +128,9 @@ uint8_t port_numa[RTE_MAX_ETHPORTS];
  */
 uint8_t rxring_numa[RTE_MAX_ETHPORTS];
 
+int proc_id = 0;
+unsigned num_procs = 1;
+
 /*
  * Store specified sockets on which TX ring to be used by ports
  * is allocated.
@@ -978,16 +984,36 @@ mbuf_pool_create(uint16_t mbuf_seg_size, unsigned nb_mbuf,
 			/* wrapper to rte_mempool_create() */
 			TESTPMD_LOG(INFO, "preferred mempool ops selected: %s\n",
 					rte_mbuf_best_mempool_ops());
+#ifdef MULTIPLE_PROCESS_HANDLE
+			if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+				rte_mp = rte_pktmbuf_pool_create(pool_name,
+					 nb_mbuf, mb_mempool_cache, 0,
+					 mbuf_seg_size, socket_id);
+			else
+				rte_mp = rte_mempool_lookup(pool_name);
+#else
 			rte_mp = rte_pktmbuf_pool_create(pool_name, nb_mbuf,
 				mb_mempool_cache, 0, mbuf_seg_size, socket_id);
+#endif
 			break;
 		}
 	case MP_ALLOC_ANON:
 		{
+#ifdef MULTIPLE_PROCESS_HANDLE
+			if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+				rte_mp = rte_mempool_create_empty(pool_name,
+					nb_mbuf, mb_size,
+					(unsigned int)mb_mempool_cache,
+					sizeof(struct rte_pktmbuf_pool_private),
+					socket_id, 0);
+			else
+				rte_mp = rte_mempool_lookup(pool_name);
+#else
 			rte_mp = rte_mempool_create_empty(pool_name, nb_mbuf,
 				mb_size, (unsigned int) mb_mempool_cache,
 				sizeof(struct rte_pktmbuf_pool_private),
 				socket_id, mempool_flags);
+#endif
 			if (rte_mp == NULL)
 				goto err;
 
@@ -1017,9 +1043,18 @@ mbuf_pool_create(uint16_t mbuf_seg_size, unsigned nb_mbuf,
 
 			TESTPMD_LOG(INFO, "preferred mempool ops selected: %s\n",
 					rte_mbuf_best_mempool_ops());
+#ifdef MULTIPLE_PROCESS_HANDLE
+			if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+				rte_mp = rte_pktmbuf_pool_create(pool_name,
+					 nb_mbuf, mb_mempool_cache, 0,
+					 mbuf_seg_size, heap_socket);
+			else
+				rte_mp = rte_mempool_lookup(pool_name);
+#else
 			rte_mp = rte_pktmbuf_pool_create(pool_name, nb_mbuf,
 					mb_mempool_cache, 0, mbuf_seg_size,
 					heap_socket);
+#endif
 			break;
 		}
 	case MP_ALLOC_XBUF:
@@ -2485,21 +2520,28 @@ start_port(portid_t pid)
 				return -1;
 			}
 			/* configure port */
-			diag = rte_eth_dev_configure(pi, nb_rxq + nb_hairpinq,
+			if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+				diag = rte_eth_dev_configure(pi,
+						     nb_rxq + nb_hairpinq,
 						     nb_txq + nb_hairpinq,
 						     &(port->dev_conf));
-			if (diag != 0) {
-				if (rte_atomic16_cmpset(&(port->port_status),
-				RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0)
-					printf("Port %d can not be set back "
-							"to stopped\n", pi);
-				printf("Fail to configure port %d\n", pi);
-				/* try to reconfigure port next time */
-				port->need_reconfig = 1;
-				return -1;
+				if (diag != 0) {
+					if (rte_atomic16_cmpset(
+							&(port->port_status),
+							RTE_PORT_HANDLING,
+							RTE_PORT_STOPPED) == 0)
+						printf("Port %d can not be set "
+						       "back to stopped\n", pi);
+					printf("Fail to configure port %d\n",
+						pi);
+					/* try to reconfigure port next time */
+					port->need_reconfig = 1;
+					return -1;
+				}
 			}
 		}
-		if (port->need_reconfig_queues > 0) {
+		if (port->need_reconfig_queues > 0 &&
+		    rte_eal_process_type() == RTE_PROC_PRIMARY) {
 			port->need_reconfig_queues = 0;
 			/* setup tx queues */
 			for (qi = 0; qi < nb_txq; qi++) {
@@ -2600,15 +2642,18 @@ start_port(portid_t pid)
 		cnt_pi++;
 
 		/* start port */
-		if (rte_eth_dev_start(pi) < 0) {
-			printf("Fail to start port %d\n", pi);
-
-			/* Fail to setup rx queue, return */
-			if (rte_atomic16_cmpset(&(port->port_status),
-				RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0)
-				printf("Port %d can not be set back to "
-							"stopped\n", pi);
-			continue;
+		if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+			diag = rte_eth_dev_start(pi);
+			if (diag < 0) {
+				printf("Fail to start port %d\n", pi);
+
+				/* Fail to setup rx queue, return */
+				if (rte_atomic16_cmpset(&(port->port_status),
+					RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0)
+					printf("Port %d can not be set back to "
+								"stopped\n", pi);
+				continue;
+			}
 		}
 
 		if (rte_atomic16_cmpset(&(port->port_status),
@@ -2737,7 +2782,7 @@ stop_port(portid_t pid)
 		if (port->flow_list)
 			port_flow_flush(pi);
 
-		if (rte_eth_dev_stop(pi) != 0)
+		if (rte_eal_process_type() == RTE_PROC_PRIMARY && rte_eth_dev_stop(pi) != 0)
 			RTE_LOG(ERR, EAL, "rte_eth_dev_stop failed for port %u\n",
 				pi);
 
@@ -2806,8 +2851,10 @@ close_port(portid_t pid)
 			continue;
 		}
 
-		port_flow_flush(pi);
-		rte_eth_dev_close(pi);
+		if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+			port_flow_flush(pi);
+		if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+			rte_eth_dev_close(pi);
 	}
 
 	remove_invalid_ports();
@@ -3071,7 +3118,7 @@ pmd_test_exit(void)
 		}
 	}
 	for (i = 0 ; i < RTE_DIM(mempools) ; i++) {
-		if (mempools[i])
+		if (rte_eal_process_type() == RTE_PROC_PRIMARY && mempools[i])
 			rte_mempool_free(mempools[i]);
 	}
 
@@ -3519,6 +3566,10 @@ init_port_dcb_config(portid_t pid,
 	int retval;
 	uint16_t i;
 
+	if (num_procs > 1) {
+		printf("The multi-process feature doesn't support dcb.\n");
+		return -ENOTSUP;
+	}
 	rte_port = &ports[pid];
 
 	memset(&port_conf, 0, sizeof(struct rte_eth_conf));
@@ -3617,13 +3668,6 @@ init_port(void)
 }
 
 static void
-force_quit(void)
-{
-	pmd_test_exit();
-	prompt_exit();
-}
-
-static void
 print_stats(void)
 {
 	uint8_t i;
@@ -3654,12 +3698,16 @@ signal_handler(int signum)
 		if (latencystats_enabled != 0)
 			rte_latencystats_uninit();
 #endif
-		force_quit();
 		/* Set flag to indicate the force termination. */
 		f_quit = 1;
-		/* exit with the expected status */
-		signal(signum, SIG_DFL);
-		kill(getpid(), signum);
+		if (interactive == 1) {
+			dup2(testpmd_cl->s_in, testpmd_fd_copy);
+			close(testpmd_cl->s_in);
+		} else {
+			dup2(0, testpmd_fd_copy);
+			close(0);
+		}
+
 	}
 }
 
@@ -3684,10 +3732,6 @@ main(int argc, char** argv)
 		rte_exit(EXIT_FAILURE, "Cannot init EAL: %s\n",
 			 rte_strerror(rte_errno));
 
-	if (rte_eal_process_type() == RTE_PROC_SECONDARY)
-		rte_exit(EXIT_FAILURE,
-			 "Secondary process type not supported.\n");
-
 	ret = register_eth_event_callback();
 	if (ret != 0)
 		rte_exit(EXIT_FAILURE, "Cannot register for ethdev events");
@@ -3783,8 +3827,10 @@ main(int argc, char** argv)
 		}
 	}
 
-	if (!no_device_start && start_port(RTE_PORT_ALL) != 0)
+	if (!no_device_start && start_port(RTE_PORT_ALL) != 0) {
+		pmd_test_exit();
 		rte_exit(EXIT_FAILURE, "Start ports failed\n");
+	}
 
 	/* set all ports to promiscuous mode by default */
 	RTE_ETH_FOREACH_DEV(port_id) {
@@ -3830,6 +3876,8 @@ main(int argc, char** argv)
 		}
 		prompt();
 		pmd_test_exit();
+		if (unlikely(f_quit == 1))
+			prompt_exit();
 	} else
 #endif
 	{
@@ -3865,6 +3913,11 @@ main(int argc, char** argv)
 		printf("Press enter to exit\n");
 		rc = read(0, &c, 1);
 		pmd_test_exit();
+		if (unlikely(f_quit == 1)) {
+			dup2(testpmd_fd_copy, 0);
+			close(testpmd_fd_copy);
+			prompt_exit();
+		}
 		if (rc < 0)
 			return 1;
 	}
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 5f23162..8629c57 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -13,6 +13,7 @@
 #include <rte_gso.h>
 #include <cmdline.h>
 #include <sys/queue.h>
+#include  "cmdline.h"
 
 #define RTE_PORT_ALL            (~(portid_t)0x0)
 
@@ -24,6 +25,10 @@
 #define RTE_PORT_CLOSED         (uint16_t)2
 #define RTE_PORT_HANDLING       (uint16_t)3
 
+uint8_t f_quit;
+int testpmd_fd_copy;
+struct cmdline *testpmd_cl;
+
 /*
  * It is used to allocate the memory for hash key.
  * The hash key size is NIC dependent.
@@ -421,6 +426,8 @@ extern uint64_t noisy_lkup_mem_sz;
 extern uint64_t noisy_lkup_num_writes;
 extern uint64_t noisy_lkup_num_reads;
 extern uint64_t noisy_lkup_num_reads_writes;
+extern int proc_id;
+extern unsigned num_procs;
 
 extern uint8_t dcb_config;
 extern uint8_t dcb_test;
-- 
2.7.4


^ permalink raw reply	[flat|nested] 80+ messages in thread
* Re: [dpdk-dev] [PATCH v13] app/testpmd: support multi-process
@ 2021-04-28 12:10 Singh, Aman Deep
  2021-04-29 10:57 ` Min Hu (Connor)
  0 siblings, 1 reply; 80+ messages in thread
From: Singh, Aman Deep @ 2021-04-28 12:10 UTC (permalink / raw)
  To: Min Hu (Connor, dev
  Cc: Mcnamara, John, Kovacevic, Marko, Burakov, Anatoly,
	andrew.rybchenko, thomas, Li, Xiaoyun, Yigit, Ferruh

This patch adds multi-process support for testpmd.

The test cmd example as follows:

the primary cmd:

./dpdk-testpmd -a xxx --proc-type=auto -l 0-1 -- -i \

--rxq=4 --txq=4 --num-procs=2 --proc-id=0



the secondary cmd:

./dpdk-testpmd -a xxx --proc-type=auto -l 2-3 -- -i \

--rxq=4 --txq=4 --num-procs=2 --proc-id=1



Signed-off-by: Min Hu (Connor) <humin29@huawei.com<mailto:humin29@huawei.com>>

Signed-off-by: Lijun Ou <oulijun@huawei.com<mailto:oulijun@huawei.com>>

Acked-by: Xiaoyun Li <xiaoyun.li@intel.com<mailto:xiaoyun.li@intel.com>>

Acked-by: Ajit Khaparde <ajit.khaparde@broadcom.com<mailto:ajit.khaparde@broadcom.com>>

Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com<mailto:ferruh.yigit@intel.com>>

<snip>



Acked-by: Aman Deep Singh <aman.deep.singh@intel.com<mailto:aman.deep.singh@intel.com>>

Tested-by: Aman Deep Singh <aman.deep.singh@intel.com<mailto:aman.deep.singh@intel.com>>


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

end of thread, other threads:[~2021-09-08  0:49 UTC | newest]

Thread overview: 80+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-08  9:46 [dpdk-dev] [RFC] app/testpmd: support multi-process Lijun Ou
2021-01-08 10:28 ` Ferruh Yigit
2021-01-09  9:54   ` oulijun
2021-01-10 12:32 ` Wisam Monther
2021-01-12 14:13   ` oulijun
2021-01-12 14:21     ` Wisam Monther
2021-01-14  2:46       ` oulijun
2021-01-20 14:06 ` [dpdk-dev] [RFC V2] " Lijun Ou
2021-03-05  1:04   ` [dpdk-dev] [PATCH] " Lijun Ou
2021-03-05  4:05     ` Ajit Khaparde
2021-03-10 11:11       ` Min Hu (Connor)
2021-03-11  2:47     ` [dpdk-dev] [PATCH v2] " Min Hu (Connor)
2021-03-22  2:27       ` Ajit Khaparde
2021-03-22  6:35         ` Min Hu (Connor)
2021-06-15 12:23       ` [dpdk-dev] [PATCH v14] " Min Hu (Connor)
2021-07-02 12:09       ` [dpdk-dev] [PATCH v15] " Andrew Rybchenko
2021-07-02 12:47         ` Andrew Rybchenko
2021-07-08 12:20           ` Min Hu (Connor)
2021-07-08 12:30             ` Andrew Rybchenko
2021-07-08 12:51               ` Min Hu (Connor)
2021-07-10  3:50       ` [dpdk-dev] [PATCH v16] " Min Hu (Connor)
2021-07-24 11:45         ` Thomas Monjalon
2021-07-26  0:26           ` Min Hu (Connor)
2021-07-26  6:30             ` Thomas Monjalon
2021-07-26  7:28               ` Min Hu (Connor)
2021-08-02  1:51                 ` Min Hu (Connor)
2021-08-02  8:03                   ` Thomas Monjalon
2021-08-16 18:12                     ` Singh, Aman Deep
2021-08-24 12:18                       ` Ferruh Yigit
2021-08-24 13:27                         ` Min Hu (Connor)
2021-08-25  2:06       ` [dpdk-dev] [PATCH v17] " Min Hu (Connor)
2021-09-07 13:23         ` Ferruh Yigit
2021-09-08  0:48           ` Min Hu (Connor)
2021-03-11  9:07     ` [dpdk-dev] [PATCH v3] " Min Hu (Connor)
2021-03-20  0:58       ` Min Hu (Connor)
2021-03-22  7:07     ` [dpdk-dev] [PATCH v4] " Min Hu (Connor)
2021-03-22 11:19       ` Ferruh Yigit
2021-03-24  8:08       ` Li, Xiaoyun
2021-03-25 13:32         ` Min Hu (Connor)
2021-03-25 23:25           ` Ajit Khaparde
2021-03-26  6:46             ` Min Hu (Connor)
2021-03-25 13:17     ` [dpdk-dev] [PATCH v5] " Min Hu (Connor)
2021-03-26  6:46     ` [dpdk-dev] [PATCH v6] " Min Hu (Connor)
2021-03-26  8:52     ` [dpdk-dev] [PATCH v7] " Min Hu (Connor)
2021-03-29  7:51       ` Li, Xiaoyun
2021-03-30  1:48         ` Min Hu (Connor)
2021-03-30  1:48     ` [dpdk-dev] [PATCH v8] " Min Hu (Connor)
2021-03-30  2:17       ` Li, Xiaoyun
2021-03-30  6:36         ` Min Hu (Connor)
2021-03-30  3:11       ` Ajit Khaparde
2021-03-30  6:41         ` Min Hu (Connor)
2021-03-30 10:19           ` Ferruh Yigit
2021-03-30 10:43             ` Min Hu (Connor)
2021-04-08 10:32               ` Min Hu (Connor)
2021-04-08 13:27                 ` Ferruh Yigit
2021-04-09  0:45                   ` Min Hu (Connor)
2021-04-12 16:37       ` Ferruh Yigit
2021-04-15  7:54         ` Ferruh Yigit
2021-04-16  2:20           ` Min Hu (Connor)
2021-04-16  1:52     ` [dpdk-dev] [PATCH v9] " Min Hu (Connor)
2021-04-16 16:30       ` Ferruh Yigit
2021-04-17  6:12         ` Min Hu (Connor)
2021-04-17  6:12     ` [dpdk-dev] [PATCH v10] " Min Hu (Connor)
2021-04-17 22:21       ` Ferruh Yigit
2021-04-19  1:03         ` Min Hu (Connor)
2021-04-19  1:03     ` [dpdk-dev] [PATCH v11] " Min Hu (Connor)
2021-04-19 13:42       ` Ferruh Yigit
2021-04-21  9:08         ` Min Hu (Connor)
2021-04-21  8:36     ` [dpdk-dev] [PATCH v12] " Min Hu (Connor)
2021-04-22  1:18     ` [dpdk-dev] [PATCH v13] " Min Hu (Connor)
2021-06-08  8:42       ` Andrew Rybchenko
2021-06-08 10:22         ` Thomas Monjalon
2021-06-08 10:39           ` Andrew Rybchenko
2021-06-08 12:02             ` Thomas Monjalon
2021-06-08 12:36             ` Ferruh Yigit
2021-06-15 12:04         ` Min Hu (Connor)
2021-04-28 12:10 Singh, Aman Deep
2021-04-29 10:57 ` Min Hu (Connor)
2021-04-29 11:25   ` Ferruh Yigit
2021-04-29 11:34     ` Min Hu (Connor)

DPDK patches and discussions

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://inbox.dpdk.org/dev/0 dev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 dev dev/ https://inbox.dpdk.org/dev \
		dev@dpdk.org
	public-inbox-index dev

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://inbox.dpdk.org/inbox.dpdk.dev


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git