[v3] net/pcap: create null Rx function

Message ID 20190717080846.19871-1-aideen.mcloughlin@intel.com (mailing list archive)
State Accepted, archived
Delegated to: Ferruh Yigit
Headers
Series [v3] net/pcap: create null Rx function |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK
ci/intel-Performance-Testing success Performance Testing PASS
ci/mellanox-Performance-Testing success Performance Testing PASS

Commit Message

A.McLoughlin July 17, 2019, 8:08 a.m. UTC
  Previously in the PCAP PMD it was only possibe to specify an rxq which
uses an iface or a pcap file. This patch creates a 'dummy Rx' function
which is used when no rx_pcap or rx_iface is passed but a tx queue is
passed. This function can be polled and receives no packets.

Signed-off-by: A.McLoughlin <aideen.mcloughlin@intel.com>
---
v1 -> v2:
* This patch supports single_iface once http://patches.dpdk.org/patch/56509/ 
is applied
* Updated documentation to document patch behavior
* Syntax fix on lines 148 to 149
* Fixed unpermitted driver aborting on line 152
v2 -> v3:
* Update release notes to reflect functionality
---
 doc/guides/nics/pcap_ring.rst          |  8 ++++
 doc/guides/rel_notes/release_19_08.rst |  6 +++
 drivers/net/pcap/rte_eth_pcap.c        | 65 +++++++++++++++++++-------
 3 files changed, 63 insertions(+), 16 deletions(-)
  

Comments

Ferruh Yigit July 17, 2019, 4:10 p.m. UTC | #1
On 7/17/2019 9:08 AM, A.McLoughlin wrote:
> Previously in the PCAP PMD it was only possibe to specify an rxq which
> uses an iface or a pcap file. This patch creates a 'dummy Rx' function
> which is used when no rx_pcap or rx_iface is passed but a tx queue is
> passed. This function can be polled and receives no packets.
> 
> Signed-off-by: A.McLoughlin <aideen.mcloughlin@intel.com>

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

Applied to dpdk-next-net/master, thanks.
  

Patch

diff --git a/doc/guides/nics/pcap_ring.rst b/doc/guides/nics/pcap_ring.rst
index fb88fa64e..cf230ae40 100644
--- a/doc/guides/nics/pcap_ring.rst
+++ b/doc/guides/nics/pcap_ring.rst
@@ -126,6 +126,14 @@  Runtime Config Options
 
  In this case, one tx drop queue is created for each rxq on that device.
 
+ - Receive no packets on Rx
+
+ The user may want to run without receiving any packets on Rx. This can be done by not providing a rx_pcap or rx_iface, for example::
+
+   --vdev 'net_pcap0,tx_pcap=file_tx.pcap'
+
+In this case, one dummy rx queue is created for each tx queue argument passed
+
 Examples of Usage
 ^^^^^^^^^^^^^^^^^
 
diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index 4a1fd8dd8..7fd73e4ab 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -141,6 +141,12 @@  New Features
   device to be received repeatedly at a high rate. This can be useful for quick
   performance testing of DPDK apps.
 
+* **Enabled Receiving no packets on Rx.**
+
+  Added function to allow users to run without receiving any packets on Rx.
+  When function is called, a dummy queue is created for each Tx queue argument
+  passed.
+
 * **Added a FPGA_LTE_FEC bbdev PMD.**
 
   Added the new ``fpga_lte_fec`` bbdev driver for the Intel® FPGA PAC
diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c
index 26e85183e..c66e8cd8a 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/rte_eth_pcap.c
@@ -112,6 +112,8 @@  struct pmd_devargs_all {
 	int single_iface;
 	unsigned int is_tx_pcap;
 	unsigned int is_tx_iface;
+	unsigned int is_rx_pcap;
+	unsigned int is_rx_iface;
 	unsigned int infinite_rx;
 };
 
@@ -295,6 +297,14 @@  eth_pcap_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 	return num_rx;
 }
 
+static uint16_t
+eth_null_rx(void *queue __rte_unused,
+		struct rte_mbuf **bufs __rte_unused,
+		uint16_t nb_pkts __rte_unused)
+{
+	return 0;
+}
+
 static inline void
 calculate_timestamp(struct timeval *ts) {
 	uint64_t cycles;
@@ -1316,8 +1326,11 @@  eth_from_pcaps(struct rte_vdev_device *vdev,
 	/* Assign rx ops. */
 	if (infinite_rx)
 		eth_dev->rx_pkt_burst = eth_pcap_rx_infinite;
-	else
+	else if (devargs_all->is_rx_pcap || devargs_all->is_rx_iface ||
+			single_iface)
 		eth_dev->rx_pkt_burst = eth_pcap_rx;
+	else
+		eth_dev->rx_pkt_burst = eth_null_rx;
 
 	/* Assign tx ops. */
 	if (devargs_all->is_tx_pcap)
@@ -1335,13 +1348,12 @@  static int
 pmd_pcap_probe(struct rte_vdev_device *dev)
 {
 	const char *name;
-	unsigned int is_rx_pcap = 0;
 	struct rte_kvargs *kvlist;
 	struct pmd_devargs pcaps = {0};
 	struct pmd_devargs dumpers = {0};
 	struct rte_eth_dev *eth_dev =  NULL;
 	struct pmd_internals *internal;
-	int ret;
+	int ret = 0;
 
 	struct pmd_devargs_all devargs_all = {
 		.single_iface = 0,
@@ -1404,13 +1416,22 @@  pmd_pcap_probe(struct rte_vdev_device *dev)
 	}
 
 	/*
-	 * We check whether we want to open a RX stream from a real NIC or a
-	 * pcap file
+	 * We check whether we want to open a RX stream from a real NIC, a
+	 * pcap file or open a dummy RX stream
 	 */
-	is_rx_pcap = rte_kvargs_count(kvlist, ETH_PCAP_RX_PCAP_ARG) ? 1 : 0;
+	devargs_all.is_rx_pcap =
+		rte_kvargs_count(kvlist, ETH_PCAP_RX_PCAP_ARG) ? 1 : 0;
+	devargs_all.is_rx_iface =
+		rte_kvargs_count(kvlist, ETH_PCAP_RX_IFACE_ARG) ? 1 : 0;
 	pcaps.num_of_queue = 0;
 
-	if (is_rx_pcap) {
+	devargs_all.is_tx_pcap =
+		rte_kvargs_count(kvlist, ETH_PCAP_TX_PCAP_ARG) ? 1 : 0;
+	devargs_all.is_tx_iface =
+		rte_kvargs_count(kvlist, ETH_PCAP_TX_IFACE_ARG) ? 1 : 0;
+	dumpers.num_of_queue = 0;
+
+	if (devargs_all.is_rx_pcap) {
 		/*
 		 * We check whether we want to infinitely rx the pcap file.
 		 */
@@ -1436,11 +1457,29 @@  pmd_pcap_probe(struct rte_vdev_device *dev)
 
 		ret = rte_kvargs_process(kvlist, ETH_PCAP_RX_PCAP_ARG,
 				&open_rx_pcap, &pcaps);
-	} else {
+	} else if (devargs_all.is_rx_iface) {
 		ret = rte_kvargs_process(kvlist, NULL,
 				&rx_iface_args_process, &pcaps);
-	}
+	} else if (devargs_all.is_tx_iface || devargs_all.is_tx_pcap) {
+		unsigned int i;
+
+		/* Count number of tx queue args passed before dummy rx queue
+		 * creation so a dummy rx queue can be created for each tx queue
+		 */
+		unsigned int num_tx_queues =
+			(rte_kvargs_count(kvlist, ETH_PCAP_TX_PCAP_ARG) +
+			rte_kvargs_count(kvlist, ETH_PCAP_TX_IFACE_ARG));
 
+		PMD_LOG(INFO, "Creating null rx queue since no rx queues were provided.");
+
+		/* Creating a dummy rx queue for each tx queue passed */
+		for (i = 0; i < num_tx_queues; i++)
+			ret = add_queue(&pcaps, "dummy_rx", "rx_null", NULL,
+					NULL);
+	} else {
+		PMD_LOG(ERR, "Error - No rx or tx queues provided");
+		ret = -ENOENT;
+	}
 	if (ret < 0)
 		goto free_kvlist;
 
@@ -1448,12 +1487,6 @@  pmd_pcap_probe(struct rte_vdev_device *dev)
 	 * We check whether we want to open a TX stream to a real NIC,
 	 * a pcap file, or drop packets on tx
 	 */
-	devargs_all.is_tx_pcap =
-		rte_kvargs_count(kvlist, ETH_PCAP_TX_PCAP_ARG) ? 1 : 0;
-	devargs_all.is_tx_iface =
-		rte_kvargs_count(kvlist, ETH_PCAP_TX_IFACE_ARG) ? 1 : 0;
-	dumpers.num_of_queue = 0;
-
 	if (devargs_all.is_tx_pcap) {
 		ret = rte_kvargs_process(kvlist, ETH_PCAP_TX_PCAP_ARG,
 				&open_tx_pcap, &dumpers);
@@ -1467,7 +1500,7 @@  pmd_pcap_probe(struct rte_vdev_device *dev)
 
 		/* Add 1 dummy queue per rxq which counts and drops packets. */
 		for (i = 0; i < pcaps.num_of_queue; i++)
-			ret = add_queue(&dumpers, "dummy", "tx_drop", NULL,
+			ret = add_queue(&dumpers, "dummy_tx", "tx_drop", NULL,
 					NULL);
 	}