[dpdk-dev] net/pcap: remove single interface constraint (v2)

Message ID BFDB638E-C70B-4709-8C8D-5E7153D60AFA@gmail.com (mailing list archive)
State Changes Requested, archived
Delegated to: Ferruh Yigit
Headers

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/Intel-compilation success Compilation OK

Commit Message

Ilya Matveychikov Nov. 5, 2017, 10:15 a.m. UTC
  Hello folks,

This patch removes single interface constraint from the libpcap-based PMD.
The problem it solves is to allow PCAP device consists of more than single
device:

 # testpmd --vdev net_pcap0,iface=vethA,iface=vethB,iface=vethC and so..

I found the issue when performed RSS emulation based on PCAP PMD. For my
task I had to create multi-queue PCAP device based on a number of veth
devices which in turn was combined in bonding device.

Signed-off-by: Ilya V. Matveychikov <matvejchikov@gmail.com>
---
drivers/net/pcap/rte_eth_pcap.c | 77 +++++++++++++++++++++++------------------
1 file changed, 43 insertions(+), 34 deletions(-)

--
2.7.4
  

Comments

Ferruh Yigit Nov. 6, 2017, 10:57 p.m. UTC | #1
On 11/5/2017 2:15 AM, Ilya Matveychikov wrote:
> Hello folks,
> 
> This patch removes single interface constraint from the libpcap-based PMD.
> The problem it solves is to allow PCAP device consists of more than single
> device:
> 
>  # testpmd --vdev net_pcap0,iface=vethA,iface=vethB,iface=vethC and so..
> 
> I found the issue when performed RSS emulation based on PCAP PMD. For my
> task I had to create multi-queue PCAP device based on a number of veth
> devices which in turn was combined in bonding device.

Hi Ilya,

Overall patch looks good.

But patch does two things,
1- remove "single_iface" variable and replace it with
  "internals->tx_queue[0].pcap == internals->rx_queue[0].pcap" checks.

  perhaps variable name is misleading but it is to say Rx and Tx are not
different, but single interface, which is still valid.

2- Add multi-queue support. For this case, replace hardcoded queue 0 to variable
length.


Would you mind keeping "single_iface" as it is but add multi-queue support?

Also, multi-queue support for other types seems broken, if you have time can you
please send a patch to fix them as well, see below [1] for detail.


Thanks,
ferruh

> 
> Signed-off-by: Ilya V. Matveychikov <matvejchikov@gmail.com>

<...>

> @@ -737,9 +744,14 @@ open_rx_tx_iface(const char *key, const char *value, void *extra_args)
> 	if (open_single_iface(iface, &pcap) < 0)
> 		return -1;
> 
> -	tx->queue[0].pcap = pcap;
> -	tx->queue[0].name = iface;
> -	tx->queue[0].type = key;
> +	for (i = 0; i < tx->num_of_queue; i++) {
> +		if (tx->queue[i].pcap == NULL) {

[1]: This check is missing for open_rx_iface, open_tx_iface, open_rx_pcap and
open_tx_pcap.

It is possible to implement as:

for (i = 0; i < rx->num_of_queue; i++) {
  if (rx->queue[i].name)
	continue;

  <this part is same old code>

  break;
}

> +			tx->queue[i].pcap = pcap;
> +			tx->queue[i].name = iface;
> +			tx->queue[i].type = key;
> +			break;
> +		}
> +	}
> 
> 	return 0;
> }

<...>

> @@ -953,19 +960,21 @@ pmd_pcap_probe(struct rte_vdev_device *dev)
> 	 * If iface argument is passed we open the NICs and use them for
> 	 * reading / writing
> 	 */
> -	if (rte_kvargs_count(kvlist, ETH_PCAP_IFACE_ARG) == 1) {
> +	if (rte_kvargs_count(kvlist, ETH_PCAP_IFACE_ARG)) {
> +		int i, queues = rte_kvargs_count(kvlist, ETH_PCAP_IFACE_ARG);

Can prevent duplicate call of rte_kvargs_count() by moving queues above if.

<...>
  

Patch

diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c
index defb3b4..ae03c3b 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/rte_eth_pcap.c
@@ -94,7 +94,6 @@  struct pmd_internals {
	struct pcap_rx_queue rx_queue[RTE_PMD_PCAP_MAX_QUEUES];
	struct pcap_tx_queue tx_queue[RTE_PMD_PCAP_MAX_QUEUES];
	int if_index;
-	int single_iface;
};

struct pmd_devargs {
@@ -441,15 +440,19 @@  eth_dev_start(struct rte_eth_dev *dev)
	struct pcap_rx_queue *rx;

	/* Special iface case. Single pcap is open and shared between tx/rx. */
-	if (internals->single_iface) {
-		tx = &internals->tx_queue[0];
-		rx = &internals->rx_queue[0];
-
-		if (!tx->pcap && strcmp(tx->type, ETH_PCAP_IFACE_ARG) == 0) {
-			if (open_single_iface(tx->name, &tx->pcap) < 0)
-				return -1;
-			rx->pcap = tx->pcap;
+	if (internals->tx_queue[0].pcap == internals->rx_queue[0].pcap) {
+		RTE_ASSERT(dev->data->nb_tx_queues == dev->data->nb_rx_queues);
+		for (i = 0; i < dev->data->nb_tx_queues; i++) {
+			tx = &internals->tx_queue[i];
+			rx = &internals->rx_queue[i];
+
+			if (!tx->pcap && strcmp(tx->type, ETH_PCAP_IFACE_ARG) == 0) {
+				if (open_single_iface(tx->name, &tx->pcap) < 0)
+					return -1;
+				rx->pcap = tx->pcap;
+			}
		}
+
		goto status_up;
	}

@@ -504,12 +507,15 @@  eth_dev_stop(struct rte_eth_dev *dev)
	struct pcap_rx_queue *rx;

	/* Special iface case. Single pcap is open and shared between tx/rx. */
-	if (internals->single_iface) {
-		tx = &internals->tx_queue[0];
-		rx = &internals->rx_queue[0];
-		pcap_close(tx->pcap);
-		tx->pcap = NULL;
-		rx->pcap = NULL;
+	if (internals->tx_queue[0].pcap == internals->rx_queue[0].pcap) {
+		RTE_ASSERT(dev->data->nb_tx_queues == dev->data->nb_rx_queues);
+		for (i = 0; i < dev->data->nb_tx_queues; i++) {
+			tx = &internals->tx_queue[i];
+			rx = &internals->rx_queue[i];
+			pcap_close(tx->pcap);
+			tx->pcap = NULL;
+			rx->pcap = NULL;
+		}
		goto status_down;
	}

@@ -730,6 +736,7 @@  open_tx_pcap(const char *key, const char *value, void *extra_args)
static inline int
open_rx_tx_iface(const char *key, const char *value, void *extra_args)
{
+	unsigned int i;
	const char *iface = value;
	struct pmd_devargs *tx = extra_args;
	pcap_t *pcap = NULL;
@@ -737,9 +744,14 @@  open_rx_tx_iface(const char *key, const char *value, void *extra_args)
	if (open_single_iface(iface, &pcap) < 0)
		return -1;

-	tx->queue[0].pcap = pcap;
-	tx->queue[0].name = iface;
-	tx->queue[0].type = key;
+	for (i = 0; i < tx->num_of_queue; i++) {
+		if (tx->queue[i].pcap == NULL) {
+			tx->queue[i].pcap = pcap;
+			tx->queue[i].name = iface;
+			tx->queue[i].type = key;
+			break;
+		}
+	}

	return 0;
}
@@ -901,8 +913,7 @@  static int
eth_from_pcaps(struct rte_vdev_device *vdev,
		struct pmd_devargs *rx_queues, const unsigned int nb_rx_queues,
		struct pmd_devargs *tx_queues, const unsigned int nb_tx_queues,
-		struct rte_kvargs *kvlist, int single_iface,
-		unsigned int using_dumpers)
+		struct rte_kvargs *kvlist, unsigned int using_dumpers)
{
	struct pmd_internals *internals = NULL;
	struct rte_eth_dev *eth_dev = NULL;
@@ -914,9 +925,6 @@  eth_from_pcaps(struct rte_vdev_device *vdev,
	if (ret < 0)
		return ret;

-	/* store weather we are using a single interface for rx/tx or not */
-	internals->single_iface = single_iface;
-
	eth_dev->rx_pkt_burst = eth_pcap_rx;

	if (using_dumpers)
@@ -935,7 +943,6 @@  pmd_pcap_probe(struct rte_vdev_device *dev)
	struct rte_kvargs *kvlist;
	struct pmd_devargs pcaps = {0};
	struct pmd_devargs dumpers = {0};
-	int single_iface = 0;
	int ret;

	name = rte_vdev_device_name(dev);
@@ -953,19 +960,21 @@  pmd_pcap_probe(struct rte_vdev_device *dev)
	 * If iface argument is passed we open the NICs and use them for
	 * reading / writing
	 */
-	if (rte_kvargs_count(kvlist, ETH_PCAP_IFACE_ARG) == 1) {
+	if (rte_kvargs_count(kvlist, ETH_PCAP_IFACE_ARG)) {
+		int i, queues = rte_kvargs_count(kvlist, ETH_PCAP_IFACE_ARG);

-		ret = rte_kvargs_process(kvlist, ETH_PCAP_IFACE_ARG,
-				&open_rx_tx_iface, &pcaps);
+		pcaps.num_of_queue = queues;
+		dumpers.num_of_queue = queues;

-		if (ret < 0)
-			goto free_kvlist;
+		for (i = 0; i < queues; i++) {
+			ret = rte_kvargs_process(kvlist, ETH_PCAP_IFACE_ARG,
+						 &open_rx_tx_iface, &pcaps);

-		dumpers.queue[0] = pcaps.queue[0];
+			if (ret < 0)
+				goto free_kvlist;

-		single_iface = 1;
-		pcaps.num_of_queue = 1;
-		dumpers.num_of_queue = 1;
+			dumpers.queue[i] = pcaps.queue[i];
+		}

		goto create_eth;
	}
@@ -1020,7 +1029,7 @@  pmd_pcap_probe(struct rte_vdev_device *dev)

create_eth:
	ret = eth_from_pcaps(dev, &pcaps, pcaps.num_of_queue, &dumpers,
-		dumpers.num_of_queue, kvlist, single_iface, is_tx_pcap);
+		dumpers.num_of_queue, kvlist, is_tx_pcap);

free_kvlist:
	rte_kvargs_free(kvlist);