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

Ilya Matveychikov matvejchikov at gmail.com
Sun Nov 5 08:41:14 CET 2017


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.

---
 drivers/net/pcap/rte_eth_pcap.c | 77 +++++++++++++++++++++++------------------
 1 file changed, 43 insertions(+), 34 deletions(-)

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 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 (int 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);
--
2.7.4


More information about the dev mailing list