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 <matvejchi...@gmail.com>
---
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 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);
--
2.7.4

Reply via email to