get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/4743/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 4743,
    "url": "https://patches.dpdk.org/api/patches/4743/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1431705423-16134-13-git-send-email-bruce.richardson@intel.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1431705423-16134-13-git-send-email-bruce.richardson@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1431705423-16134-13-git-send-email-bruce.richardson@intel.com",
    "date": "2015-05-15T15:56:56",
    "name": "[dpdk-dev,v2,12/19] pcap: move pcap pmd to drivers/net",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "b5fccf739a892047b50f4875e7f2b9fec05ea359",
    "submitter": {
        "id": 20,
        "url": "https://patches.dpdk.org/api/people/20/?format=api",
        "name": "Bruce Richardson",
        "email": "bruce.richardson@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1431705423-16134-13-git-send-email-bruce.richardson@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/4743/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/4743/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id E5CD55A9B;\n\tFri, 15 May 2015 17:57:19 +0200 (CEST)",
            "from mga03.intel.com (mga03.intel.com [134.134.136.65])\n\tby dpdk.org (Postfix) with ESMTP id 001DA5A5E\n\tfor <dev@dpdk.org>; Fri, 15 May 2015 17:57:10 +0200 (CEST)",
            "from fmsmga001.fm.intel.com ([10.253.24.23])\n\tby orsmga103.jf.intel.com with ESMTP; 15 May 2015 08:57:10 -0700",
            "from irvmail001.ir.intel.com ([163.33.26.43])\n\tby fmsmga001.fm.intel.com with ESMTP; 15 May 2015 08:57:09 -0700",
            "from sivswdev01.ir.intel.com (sivswdev01.ir.intel.com\n\t[10.237.217.45])\n\tby irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id\n\tt4FFv8oC030304; Fri, 15 May 2015 16:57:08 +0100",
            "from sivswdev01.ir.intel.com (localhost [127.0.0.1])\n\tby sivswdev01.ir.intel.com with ESMTP id t4FFv8aA016258;\n\tFri, 15 May 2015 16:57:08 +0100",
            "(from bricha3@localhost)\n\tby sivswdev01.ir.intel.com with  id t4FFv83Q016254;\n\tFri, 15 May 2015 16:57:08 +0100"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.13,434,1427785200\"; d=\"scan'208\";a=\"710767892\"",
        "From": "Bruce Richardson <bruce.richardson@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Fri, 15 May 2015 16:56:56 +0100",
        "Message-Id": "<1431705423-16134-13-git-send-email-bruce.richardson@intel.com>",
        "X-Mailer": "git-send-email 1.7.4.1",
        "In-Reply-To": "<1431705423-16134-1-git-send-email-bruce.richardson@intel.com>",
        "References": "<1431450315-13179-1-git-send-email-bruce.richardson@intel.com>\n\t<1431705423-16134-1-git-send-email-bruce.richardson@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v2 12/19] pcap: move pcap pmd to drivers/net",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Move pcap pmd to drivers/net directory\n\nSigned-off-by: Bruce Richardson <bruce.richardson@intel.com>\n---\n drivers/net/Makefile                         |   2 +-\n drivers/net/pcap/Makefile                    |  63 ++\n drivers/net/pcap/rte_eth_pcap.c              | 994 +++++++++++++++++++++++++++\n drivers/net/pcap/rte_pmd_pcap_version.map    |   4 +\n lib/Makefile                                 |   1 -\n lib/librte_eal/bsdapp/eal/Makefile           |   4 +-\n lib/librte_eal/linuxapp/eal/Makefile         |   2 +-\n lib/librte_pmd_pcap/Makefile                 |  63 --\n lib/librte_pmd_pcap/rte_eth_pcap.c           | 994 ---------------------------\n lib/librte_pmd_pcap/rte_pmd_pcap_version.map |   4 -\n 10 files changed, 1065 insertions(+), 1066 deletions(-)\n create mode 100644 drivers/net/pcap/Makefile\n create mode 100644 drivers/net/pcap/rte_eth_pcap.c\n create mode 100644 drivers/net/pcap/rte_pmd_pcap_version.map\n delete mode 100644 lib/librte_pmd_pcap/Makefile\n delete mode 100644 lib/librte_pmd_pcap/rte_eth_pcap.c\n delete mode 100644 lib/librte_pmd_pcap/rte_pmd_pcap_version.map",
    "diff": "diff --git a/drivers/net/Makefile b/drivers/net/Makefile\nindex bbed6f8..d9cba6c 100644\n--- a/drivers/net/Makefile\n+++ b/drivers/net/Makefile\n@@ -40,8 +40,8 @@ DIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e\n DIRS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe\n DIRS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += mlx4\n DIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += null\n+DIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += pcap\n #DIRS-$(CONFIG_RTE_LIBRTE_PMD_RING) += librte_pmd_ring\n-#DIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += librte_pmd_pcap\n #DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += librte_pmd_virtio\n #DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3\n #DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt\ndiff --git a/drivers/net/pcap/Makefile b/drivers/net/pcap/Makefile\nnew file mode 100644\nindex 0000000..0775dbc\n--- /dev/null\n+++ b/drivers/net/pcap/Makefile\n@@ -0,0 +1,63 @@\n+#   BSD LICENSE\n+#\n+#   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+#   Copyright(c) 2014 6WIND S.A.\n+#   All rights reserved.\n+#\n+#   Redistribution and use in source and binary forms, with or without\n+#   modification, are permitted provided that the following conditions\n+#   are met:\n+#\n+#     * Redistributions of source code must retain the above copyright\n+#       notice, this list of conditions and the following disclaimer.\n+#     * Redistributions in binary form must reproduce the above copyright\n+#       notice, this list of conditions and the following disclaimer in\n+#       the documentation and/or other materials provided with the\n+#       distribution.\n+#     * Neither the name of Intel Corporation nor the names of its\n+#       contributors may be used to endorse or promote products derived\n+#       from this software without specific prior written permission.\n+#\n+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+#   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+\n+include $(RTE_SDK)/mk/rte.vars.mk\n+\n+#\n+# library name\n+#\n+LIB = librte_pmd_pcap.a\n+\n+CFLAGS += -O3\n+CFLAGS += $(WERROR_FLAGS)\n+\n+EXPORT_MAP := rte_pmd_pcap_version.map\n+\n+LIBABIVER := 1\n+\n+#\n+# all source are stored in SRCS-y\n+#\n+SRCS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += rte_eth_pcap.c\n+\n+#\n+# Export include files\n+#\n+SYMLINK-y-include +=\n+\n+# this lib depends upon:\n+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += lib/librte_mbuf\n+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += lib/librte_ether\n+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += lib/librte_malloc\n+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += lib/librte_kvargs\n+\n+include $(RTE_SDK)/mk/rte.lib.mk\ndiff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c\nnew file mode 100644\nindex 0000000..ff9b534\n--- /dev/null\n+++ b/drivers/net/pcap/rte_eth_pcap.c\n@@ -0,0 +1,994 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+ *   Copyright(c) 2014 6WIND S.A.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#include <time.h>\n+#include <rte_mbuf.h>\n+#include <rte_ethdev.h>\n+#include <rte_malloc.h>\n+#include <rte_memcpy.h>\n+#include <rte_string_fns.h>\n+#include <rte_cycles.h>\n+#include <rte_kvargs.h>\n+#include <rte_dev.h>\n+\n+#include <net/if.h>\n+\n+#include <pcap.h>\n+\n+#define RTE_ETH_PCAP_SNAPSHOT_LEN 65535\n+#define RTE_ETH_PCAP_SNAPLEN 4096\n+#define RTE_ETH_PCAP_PROMISC 1\n+#define RTE_ETH_PCAP_TIMEOUT -1\n+#define ETH_PCAP_RX_PCAP_ARG  \"rx_pcap\"\n+#define ETH_PCAP_TX_PCAP_ARG  \"tx_pcap\"\n+#define ETH_PCAP_RX_IFACE_ARG \"rx_iface\"\n+#define ETH_PCAP_TX_IFACE_ARG \"tx_iface\"\n+#define ETH_PCAP_IFACE_ARG    \"iface\"\n+\n+#define ETH_PCAP_ARG_MAXLEN\t64\n+\n+static char errbuf[PCAP_ERRBUF_SIZE];\n+static struct timeval start_time;\n+static uint64_t start_cycles;\n+static uint64_t hz;\n+\n+struct pcap_rx_queue {\n+\tpcap_t *pcap;\n+\tuint8_t in_port;\n+\tstruct rte_mempool *mb_pool;\n+\tvolatile unsigned long rx_pkts;\n+\tvolatile unsigned long err_pkts;\n+\tchar name[PATH_MAX];\n+\tchar type[ETH_PCAP_ARG_MAXLEN];\n+};\n+\n+struct pcap_tx_queue {\n+\tpcap_dumper_t *dumper;\n+\tpcap_t *pcap;\n+\tvolatile unsigned long tx_pkts;\n+\tvolatile unsigned long err_pkts;\n+\tchar name[PATH_MAX];\n+\tchar type[ETH_PCAP_ARG_MAXLEN];\n+};\n+\n+struct rx_pcaps {\n+\tunsigned num_of_rx;\n+\tpcap_t *pcaps[RTE_PMD_RING_MAX_RX_RINGS];\n+\tconst char *names[RTE_PMD_RING_MAX_RX_RINGS];\n+\tconst char *types[RTE_PMD_RING_MAX_RX_RINGS];\n+};\n+\n+struct tx_pcaps {\n+\tunsigned num_of_tx;\n+\tpcap_dumper_t *dumpers[RTE_PMD_RING_MAX_TX_RINGS];\n+\tpcap_t *pcaps[RTE_PMD_RING_MAX_RX_RINGS];\n+\tconst char *names[RTE_PMD_RING_MAX_RX_RINGS];\n+\tconst char *types[RTE_PMD_RING_MAX_RX_RINGS];\n+};\n+\n+struct pmd_internals {\n+\tstruct pcap_rx_queue rx_queue[RTE_PMD_RING_MAX_RX_RINGS];\n+\tstruct pcap_tx_queue tx_queue[RTE_PMD_RING_MAX_TX_RINGS];\n+\tunsigned nb_rx_queues;\n+\tunsigned nb_tx_queues;\n+\tint if_index;\n+\tint single_iface;\n+};\n+\n+const char *valid_arguments[] = {\n+\tETH_PCAP_RX_PCAP_ARG,\n+\tETH_PCAP_TX_PCAP_ARG,\n+\tETH_PCAP_RX_IFACE_ARG,\n+\tETH_PCAP_TX_IFACE_ARG,\n+\tETH_PCAP_IFACE_ARG,\n+\tNULL\n+};\n+\n+static int open_single_tx_pcap(const char *pcap_filename, pcap_dumper_t **dumper);\n+static int open_single_rx_pcap(const char *pcap_filename, pcap_t **pcap);\n+static int open_single_iface(const char *iface, pcap_t **pcap);\n+\n+static struct ether_addr eth_addr = { .addr_bytes = { 0, 0, 0, 0x1, 0x2, 0x3 } };\n+static const char *drivername = \"Pcap PMD\";\n+static struct rte_eth_link pmd_link = {\n+\t\t.link_speed = 10000,\n+\t\t.link_duplex = ETH_LINK_FULL_DUPLEX,\n+\t\t.link_status = 0\n+};\n+\n+\n+static uint16_t\n+eth_pcap_rx(void *queue,\n+\t\tstruct rte_mbuf **bufs,\n+\t\tuint16_t nb_pkts)\n+{\n+\tunsigned i;\n+\tstruct pcap_pkthdr header;\n+\tconst u_char *packet;\n+\tstruct rte_mbuf *mbuf;\n+\tstruct pcap_rx_queue *pcap_q = queue;\n+\tuint16_t num_rx = 0;\n+\tuint16_t buf_size;\n+\n+\tif (unlikely(pcap_q->pcap == NULL || nb_pkts == 0))\n+\t\treturn 0;\n+\n+\t/* Reads the given number of packets from the pcap file one by one\n+\t * and copies the packet data into a newly allocated mbuf to return.\n+\t */\n+\tfor (i = 0; i < nb_pkts; i++) {\n+\t\t/* Get the next PCAP packet */\n+\t\tpacket = pcap_next(pcap_q->pcap, &header);\n+\t\tif (unlikely(packet == NULL))\n+\t\t\tbreak;\n+\t\telse\n+\t\t\tmbuf = rte_pktmbuf_alloc(pcap_q->mb_pool);\n+\t\tif (unlikely(mbuf == NULL))\n+\t\t\tbreak;\n+\n+\t\t/* Now get the space available for data in the mbuf */\n+\t\tbuf_size = (uint16_t)(rte_pktmbuf_data_room_size(pcap_q->mb_pool) -\n+\t\t\t\tRTE_PKTMBUF_HEADROOM);\n+\n+\t\tif (header.len <= buf_size) {\n+\t\t\t/* pcap packet will fit in the mbuf, go ahead and copy */\n+\t\t\trte_memcpy(rte_pktmbuf_mtod(mbuf, void *), packet,\n+\t\t\t\t\theader.len);\n+\t\t\tmbuf->data_len = (uint16_t)header.len;\n+\t\t\tmbuf->pkt_len = mbuf->data_len;\n+\t\t\tmbuf->port = pcap_q->in_port;\n+\t\t\tbufs[num_rx] = mbuf;\n+\t\t\tnum_rx++;\n+\t\t} else {\n+\t\t\t/* pcap packet will not fit in the mbuf, so drop packet */\n+\t\t\tRTE_LOG(ERR, PMD,\n+\t\t\t\t\t\"PCAP packet %d bytes will not fit in mbuf (%d bytes)\\n\",\n+\t\t\t\t\theader.len, buf_size);\n+\t\t\trte_pktmbuf_free(mbuf);\n+\t\t}\n+\t}\n+\tpcap_q->rx_pkts += num_rx;\n+\treturn num_rx;\n+}\n+\n+static inline void\n+calculate_timestamp(struct timeval *ts) {\n+\tuint64_t cycles;\n+\tstruct timeval cur_time;\n+\n+\tcycles = rte_get_timer_cycles() - start_cycles;\n+\tcur_time.tv_sec = cycles / hz;\n+\tcur_time.tv_usec = (cycles % hz) * 10e6 / hz;\n+\ttimeradd(&start_time, &cur_time, ts);\n+}\n+\n+/*\n+ * Callback to handle writing packets to a pcap file.\n+ */\n+static uint16_t\n+eth_pcap_tx_dumper(void *queue,\n+\t\tstruct rte_mbuf **bufs,\n+\t\tuint16_t nb_pkts)\n+{\n+\tunsigned i;\n+\tstruct rte_mbuf *mbuf;\n+\tstruct pcap_tx_queue *dumper_q = queue;\n+\tuint16_t num_tx = 0;\n+\tstruct pcap_pkthdr header;\n+\n+\tif (dumper_q->dumper == NULL || nb_pkts == 0)\n+\t\treturn 0;\n+\n+\t/* writes the nb_pkts packets to the previously opened pcap file dumper */\n+\tfor (i = 0; i < nb_pkts; i++) {\n+\t\tmbuf = bufs[i];\n+\t\tcalculate_timestamp(&header.ts);\n+\t\theader.len = mbuf->data_len;\n+\t\theader.caplen = header.len;\n+\t\tpcap_dump((u_char *)dumper_q->dumper, &header,\n+\t\t\t\trte_pktmbuf_mtod(mbuf, void*));\n+\t\trte_pktmbuf_free(mbuf);\n+\t\tnum_tx++;\n+\t}\n+\n+\t/*\n+\t * Since there's no place to hook a callback when the forwarding\n+\t * process stops and to make sure the pcap file is actually written,\n+\t * we flush the pcap dumper within each burst.\n+\t */\n+\tpcap_dump_flush(dumper_q->dumper);\n+\tdumper_q->tx_pkts += num_tx;\n+\tdumper_q->err_pkts += nb_pkts - num_tx;\n+\treturn num_tx;\n+}\n+\n+/*\n+ * Callback to handle sending packets through a real NIC.\n+ */\n+static uint16_t\n+eth_pcap_tx(void *queue,\n+\t\tstruct rte_mbuf **bufs,\n+\t\tuint16_t nb_pkts)\n+{\n+\tunsigned i;\n+\tint ret;\n+\tstruct rte_mbuf *mbuf;\n+\tstruct pcap_tx_queue *tx_queue = queue;\n+\tuint16_t num_tx = 0;\n+\n+\tif (unlikely(nb_pkts == 0 || tx_queue->pcap == NULL))\n+\t\treturn 0;\n+\n+\tfor (i = 0; i < nb_pkts; i++) {\n+\t\tmbuf = bufs[i];\n+\t\tret = pcap_sendpacket(tx_queue->pcap,\n+\t\t\t\trte_pktmbuf_mtod(mbuf, u_char *),\n+\t\t\t\tmbuf->data_len);\n+\t\tif (unlikely(ret != 0))\n+\t\t\tbreak;\n+\t\tnum_tx++;\n+\t\trte_pktmbuf_free(mbuf);\n+\t}\n+\n+\ttx_queue->tx_pkts += num_tx;\n+\ttx_queue->err_pkts += nb_pkts - num_tx;\n+\treturn num_tx;\n+}\n+\n+static int\n+eth_dev_start(struct rte_eth_dev *dev)\n+{\n+\tunsigned i;\n+\tstruct pmd_internals *internals = dev->data->dev_private;\n+\tstruct pcap_tx_queue *tx;\n+\tstruct pcap_rx_queue *rx;\n+\n+\t/* Special iface case. Single pcap is open and shared between tx/rx. */\n+\tif (internals->single_iface) {\n+\t\ttx = &internals->tx_queue[0];\n+\t\trx = &internals->rx_queue[0];\n+\n+\t\tif (!tx->pcap && strcmp(tx->type, ETH_PCAP_IFACE_ARG) == 0) {\n+\t\t\tif (open_single_iface(tx->name, &tx->pcap) < 0)\n+\t\t\t\treturn -1;\n+\t\t\trx->pcap = tx->pcap;\n+\t\t}\n+\t\tgoto status_up;\n+\t}\n+\n+\t/* If not open already, open tx pcaps/dumpers */\n+\tfor (i = 0; i < internals->nb_tx_queues; i++) {\n+\t\ttx = &internals->tx_queue[i];\n+\n+\t\tif (!tx->dumper && strcmp(tx->type, ETH_PCAP_TX_PCAP_ARG) == 0) {\n+\t\t\tif (open_single_tx_pcap(tx->name, &tx->dumper) < 0)\n+\t\t\t\treturn -1;\n+\t\t}\n+\n+\t\telse if (!tx->pcap && strcmp(tx->type, ETH_PCAP_TX_IFACE_ARG) == 0) {\n+\t\t\tif (open_single_iface(tx->name, &tx->pcap) < 0)\n+\t\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\t/* If not open already, open rx pcaps */\n+\tfor (i = 0; i < internals->nb_rx_queues; i++) {\n+\t\trx = &internals->rx_queue[i];\n+\n+\t\tif (rx->pcap != NULL)\n+\t\t\tcontinue;\n+\n+\t\tif (strcmp(rx->type, ETH_PCAP_RX_PCAP_ARG) == 0) {\n+\t\t\tif (open_single_rx_pcap(rx->name, &rx->pcap) < 0)\n+\t\t\t\treturn -1;\n+\t\t}\n+\n+\t\telse if (strcmp(rx->type, ETH_PCAP_RX_IFACE_ARG) == 0) {\n+\t\t\tif (open_single_iface(rx->name, &rx->pcap) < 0)\n+\t\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+status_up:\n+\n+\tdev->data->dev_link.link_status = 1;\n+\treturn 0;\n+}\n+\n+/*\n+ * This function gets called when the current port gets stopped.\n+ * Is the only place for us to close all the tx streams dumpers.\n+ * If not called the dumpers will be flushed within each tx burst.\n+ */\n+static void\n+eth_dev_stop(struct rte_eth_dev *dev)\n+{\n+\tunsigned i;\n+\tstruct pmd_internals *internals = dev->data->dev_private;\n+\tstruct pcap_tx_queue *tx;\n+\tstruct pcap_rx_queue *rx;\n+\n+\t/* Special iface case. Single pcap is open and shared between tx/rx. */\n+\tif (internals->single_iface) {\n+\t\ttx = &internals->tx_queue[0];\n+\t\trx = &internals->rx_queue[0];\n+\t\tpcap_close(tx->pcap);\n+\t\ttx->pcap = NULL;\n+\t\trx->pcap = NULL;\n+\t\tgoto status_down;\n+\t}\n+\n+\tfor (i = 0; i < internals->nb_tx_queues; i++) {\n+\t\ttx = &internals->tx_queue[i];\n+\n+\t\tif (tx->dumper != NULL) {\n+\t\t\tpcap_dump_close(tx->dumper);\n+\t\t\ttx->dumper = NULL;\n+\t\t}\n+\n+\t\tif (tx->pcap != NULL) {\n+\t\t\tpcap_close(tx->pcap);\n+\t\t\ttx->pcap = NULL;\n+\t\t}\n+\t}\n+\n+\tfor (i = 0; i < internals->nb_rx_queues; i++) {\n+\t\trx = &internals->rx_queue[i];\n+\n+\t\tif (rx->pcap != NULL) {\n+\t\t\tpcap_close(rx->pcap);\n+\t\t\trx->pcap = NULL;\n+\t\t}\n+\t}\n+\n+status_down:\n+\tdev->data->dev_link.link_status = 0;\n+}\n+\n+static int\n+eth_dev_configure(struct rte_eth_dev *dev __rte_unused)\n+{\n+\treturn 0;\n+}\n+\n+static void\n+eth_dev_info(struct rte_eth_dev *dev,\n+\t\tstruct rte_eth_dev_info *dev_info)\n+{\n+\tstruct pmd_internals *internals = dev->data->dev_private;\n+\tdev_info->driver_name = drivername;\n+\tdev_info->if_index = internals->if_index;\n+\tdev_info->max_mac_addrs = 1;\n+\tdev_info->max_rx_pktlen = (uint32_t) -1;\n+\tdev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;\n+\tdev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;\n+\tdev_info->min_rx_bufsize = 0;\n+\tdev_info->pci_dev = NULL;\n+}\n+\n+static void\n+eth_stats_get(struct rte_eth_dev *dev,\n+\t\tstruct rte_eth_stats *igb_stats)\n+{\n+\tunsigned i;\n+\tunsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;\n+\tconst struct pmd_internals *internal = dev->data->dev_private;\n+\n+\tfor (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS && i < internal->nb_rx_queues;\n+\t\t\ti++) {\n+\t\tigb_stats->q_ipackets[i] = internal->rx_queue[i].rx_pkts;\n+\t\trx_total += igb_stats->q_ipackets[i];\n+\t}\n+\n+\tfor (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS && i < internal->nb_tx_queues;\n+\t\t\ti++) {\n+\t\tigb_stats->q_opackets[i] = internal->tx_queue[i].tx_pkts;\n+\t\tigb_stats->q_errors[i] = internal->tx_queue[i].err_pkts;\n+\t\ttx_total += igb_stats->q_opackets[i];\n+\t\ttx_err_total += igb_stats->q_errors[i];\n+\t}\n+\n+\tigb_stats->ipackets = rx_total;\n+\tigb_stats->opackets = tx_total;\n+\tigb_stats->oerrors = tx_err_total;\n+}\n+\n+static void\n+eth_stats_reset(struct rte_eth_dev *dev)\n+{\n+\tunsigned i;\n+\tstruct pmd_internals *internal = dev->data->dev_private;\n+\tfor (i = 0; i < internal->nb_rx_queues; i++)\n+\t\tinternal->rx_queue[i].rx_pkts = 0;\n+\tfor (i = 0; i < internal->nb_tx_queues; i++) {\n+\t\tinternal->tx_queue[i].tx_pkts = 0;\n+\t\tinternal->tx_queue[i].err_pkts = 0;\n+\t}\n+}\n+\n+static void\n+eth_dev_close(struct rte_eth_dev *dev __rte_unused)\n+{\n+}\n+\n+static void\n+eth_queue_release(void *q __rte_unused)\n+{\n+}\n+\n+static int\n+eth_link_update(struct rte_eth_dev *dev __rte_unused,\n+\t\tint wait_to_complete __rte_unused)\n+{\n+\treturn 0;\n+}\n+\n+static int\n+eth_rx_queue_setup(struct rte_eth_dev *dev,\n+\t\tuint16_t rx_queue_id,\n+\t\tuint16_t nb_rx_desc __rte_unused,\n+\t\tunsigned int socket_id __rte_unused,\n+\t\tconst struct rte_eth_rxconf *rx_conf __rte_unused,\n+\t\tstruct rte_mempool *mb_pool)\n+{\n+\tstruct pmd_internals *internals = dev->data->dev_private;\n+\tstruct pcap_rx_queue *pcap_q = &internals->rx_queue[rx_queue_id];\n+\tpcap_q->mb_pool = mb_pool;\n+\tdev->data->rx_queues[rx_queue_id] = pcap_q;\n+\tpcap_q->in_port = dev->data->port_id;\n+\treturn 0;\n+}\n+\n+static int\n+eth_tx_queue_setup(struct rte_eth_dev *dev,\n+\t\tuint16_t tx_queue_id,\n+\t\tuint16_t nb_tx_desc __rte_unused,\n+\t\tunsigned int socket_id __rte_unused,\n+\t\tconst struct rte_eth_txconf *tx_conf __rte_unused)\n+{\n+\n+\tstruct pmd_internals *internals = dev->data->dev_private;\n+\tdev->data->tx_queues[tx_queue_id] = &internals->tx_queue[tx_queue_id];\n+\treturn 0;\n+}\n+\n+static const struct eth_dev_ops ops = {\n+\t.dev_start = eth_dev_start,\n+\t.dev_stop =\teth_dev_stop,\n+\t.dev_close = eth_dev_close,\n+\t.dev_configure = eth_dev_configure,\n+\t.dev_infos_get = eth_dev_info,\n+\t.rx_queue_setup = eth_rx_queue_setup,\n+\t.tx_queue_setup = eth_tx_queue_setup,\n+\t.rx_queue_release = eth_queue_release,\n+\t.tx_queue_release = eth_queue_release,\n+\t.link_update = eth_link_update,\n+\t.stats_get = eth_stats_get,\n+\t.stats_reset = eth_stats_reset,\n+};\n+\n+static struct eth_driver rte_pcap_pmd = {\n+\t.pci_drv = {\n+\t\t.name = \"rte_pcap_pmd\",\n+\t\t.drv_flags = RTE_PCI_DRV_DETACHABLE,\n+\t},\n+};\n+\n+/*\n+ * Function handler that opens the pcap file for reading a stores a\n+ * reference of it for use it later on.\n+ */\n+static int\n+open_rx_pcap(const char *key, const char *value, void *extra_args)\n+{\n+\tunsigned i;\n+\tconst char *pcap_filename = value;\n+\tstruct rx_pcaps *pcaps = extra_args;\n+\tpcap_t *pcap = NULL;\n+\n+\tfor (i = 0; i < pcaps->num_of_rx; i++) {\n+\t\tif (open_single_rx_pcap(pcap_filename, &pcap) < 0)\n+\t\t\treturn -1;\n+\n+\t\tpcaps->pcaps[i] = pcap;\n+\t\tpcaps->names[i] = pcap_filename;\n+\t\tpcaps->types[i] = key;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+open_single_rx_pcap(const char *pcap_filename, pcap_t **pcap)\n+{\n+\tif ((*pcap = pcap_open_offline(pcap_filename, errbuf)) == NULL) {\n+\t\tRTE_LOG(ERR, PMD, \"Couldn't open %s: %s\\n\", pcap_filename, errbuf);\n+\t\treturn -1;\n+\t}\n+\treturn 0;\n+}\n+\n+/*\n+ * Opens a pcap file for writing and stores a reference to it\n+ * for use it later on.\n+ */\n+static int\n+open_tx_pcap(const char *key, const char *value, void *extra_args)\n+{\n+\tunsigned i;\n+\tconst char *pcap_filename = value;\n+\tstruct tx_pcaps *dumpers = extra_args;\n+\tpcap_dumper_t *dumper;\n+\n+\tfor (i = 0; i < dumpers->num_of_tx; i++) {\n+\t\tif (open_single_tx_pcap(pcap_filename, &dumper) < 0)\n+\t\t\treturn -1;\n+\n+\t\tdumpers->dumpers[i] = dumper;\n+\t\tdumpers->names[i] = pcap_filename;\n+\t\tdumpers->types[i] = key;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+open_single_tx_pcap(const char *pcap_filename, pcap_dumper_t **dumper)\n+{\n+\tpcap_t *tx_pcap;\n+\t/*\n+\t * We need to create a dummy empty pcap_t to use it\n+\t * with pcap_dump_open(). We create big enough an Ethernet\n+\t * pcap holder.\n+\t */\n+\n+\tif ((tx_pcap = pcap_open_dead(DLT_EN10MB, RTE_ETH_PCAP_SNAPSHOT_LEN))\n+\t\t\t== NULL) {\n+\t\tRTE_LOG(ERR, PMD, \"Couldn't create dead pcap\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\t/* The dumper is created using the previous pcap_t reference */\n+\tif ((*dumper = pcap_dump_open(tx_pcap, pcap_filename)) == NULL) {\n+\t\tRTE_LOG(ERR, PMD, \"Couldn't open %s for writing.\\n\", pcap_filename);\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * pcap_open_live wrapper function\n+ */\n+static inline int\n+open_iface_live(const char *iface, pcap_t **pcap) {\n+\t*pcap = pcap_open_live(iface, RTE_ETH_PCAP_SNAPLEN,\n+\t\t\tRTE_ETH_PCAP_PROMISC, RTE_ETH_PCAP_TIMEOUT, errbuf);\n+\n+\tif (*pcap == NULL) {\n+\t\tRTE_LOG(ERR, PMD, \"Couldn't open %s: %s\\n\", iface, errbuf);\n+\t\treturn -1;\n+\t}\n+\treturn 0;\n+}\n+\n+/*\n+ * Opens an interface for reading and writing\n+ */\n+static inline int\n+open_rx_tx_iface(const char *key, const char *value, void *extra_args)\n+{\n+\tconst char *iface = value;\n+\tstruct rx_pcaps *pcaps = extra_args;\n+\tpcap_t *pcap = NULL;\n+\n+\tif (open_single_iface(iface, &pcap) < 0)\n+\t\treturn -1;\n+\n+\tpcaps->pcaps[0] = pcap;\n+\tpcaps->names[0] = iface;\n+\tpcaps->types[0] = key;\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Opens a NIC for reading packets from it\n+ */\n+static inline int\n+open_rx_iface(const char *key, const char *value, void *extra_args)\n+{\n+\tunsigned i;\n+\tconst char *iface = value;\n+\tstruct rx_pcaps *pcaps = extra_args;\n+\tpcap_t *pcap = NULL;\n+\n+\tfor (i = 0; i < pcaps->num_of_rx; i++) {\n+\t\tif (open_single_iface(iface, &pcap) < 0)\n+\t\t\treturn -1;\n+\t\tpcaps->pcaps[i] = pcap;\n+\t\tpcaps->names[i] = iface;\n+\t\tpcaps->types[i] = key;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Opens a NIC for writing packets to it\n+ */\n+static int\n+open_tx_iface(const char *key, const char *value, void *extra_args)\n+{\n+\tunsigned i;\n+\tconst char *iface = value;\n+\tstruct tx_pcaps *pcaps = extra_args;\n+\tpcap_t *pcap;\n+\n+\tfor (i = 0; i < pcaps->num_of_tx; i++) {\n+\t\tif (open_single_iface(iface, &pcap) < 0)\n+\t\t\treturn -1;\n+\t\tpcaps->pcaps[i] = pcap;\n+\t\tpcaps->names[i] = iface;\n+\t\tpcaps->types[i] = key;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+open_single_iface(const char *iface, pcap_t **pcap)\n+{\n+\tif (open_iface_live(iface, pcap) < 0) {\n+\t\tRTE_LOG(ERR, PMD, \"Couldn't open interface %s\\n\", iface);\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+rte_pmd_init_internals(const char *name, const unsigned nb_rx_queues,\n+\t\tconst unsigned nb_tx_queues,\n+\t\tconst unsigned numa_node,\n+\t\tstruct pmd_internals **internals,\n+\t\tstruct rte_eth_dev **eth_dev,\n+\t\tstruct rte_kvargs *kvlist)\n+{\n+\tstruct rte_eth_dev_data *data = NULL;\n+\tstruct rte_pci_device *pci_dev = NULL;\n+\tunsigned k_idx;\n+\tstruct rte_kvargs_pair *pair = NULL;\n+\n+\tfor (k_idx = 0; k_idx < kvlist->count; k_idx++) {\n+\t\tpair = &kvlist->pairs[k_idx];\n+\t\tif (strstr(pair->key, ETH_PCAP_IFACE_ARG) != NULL)\n+\t\t\tbreak;\n+\t}\n+\n+\tRTE_LOG(INFO, PMD,\n+\t\t\t\"Creating pcap-backed ethdev on numa socket %u\\n\", numa_node);\n+\n+\t/* now do all data allocation - for eth_dev structure, dummy pci driver\n+\t * and internal (private) data\n+\t */\n+\tdata = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);\n+\tif (data == NULL)\n+\t\tgoto error;\n+\n+\tpci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);\n+\tif (pci_dev == NULL)\n+\t\tgoto error;\n+\n+\t*internals = rte_zmalloc_socket(name, sizeof(**internals), 0, numa_node);\n+\tif (*internals == NULL)\n+\t\tgoto error;\n+\n+\t/* reserve an ethdev entry */\n+\t*eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL);\n+\tif (*eth_dev == NULL)\n+\t\tgoto error;\n+\n+\t/* check length of device name */\n+\tif ((strlen((*eth_dev)->data->name) + 1) > sizeof(data->name))\n+\t\tgoto error;\n+\n+\t/* now put it all together\n+\t * - store queue data in internals,\n+\t * - store numa_node info in pci_driver\n+\t * - point eth_dev_data to internals and pci_driver\n+\t * - and point eth_dev structure to new eth_dev_data structure\n+\t */\n+\t/* NOTE: we'll replace the data element, of originally allocated eth_dev\n+\t * so the rings are local per-process */\n+\n+\t(*internals)->nb_rx_queues = nb_rx_queues;\n+\t(*internals)->nb_tx_queues = nb_tx_queues;\n+\n+\tif (pair == NULL)\n+\t\t(*internals)->if_index = 0;\n+\telse\n+\t\t(*internals)->if_index = if_nametoindex(pair->value);\n+\n+\tpci_dev->numa_node = numa_node;\n+\n+\tdata->dev_private = *internals;\n+\tdata->port_id = (*eth_dev)->data->port_id;\n+\tsnprintf(data->name, sizeof(data->name), \"%s\", (*eth_dev)->data->name);\n+\tdata->nb_rx_queues = (uint16_t)nb_rx_queues;\n+\tdata->nb_tx_queues = (uint16_t)nb_tx_queues;\n+\tdata->dev_link = pmd_link;\n+\tdata->mac_addrs = &eth_addr;\n+\tstrncpy(data->name,\n+\t\t(*eth_dev)->data->name, strlen((*eth_dev)->data->name));\n+\n+\t(*eth_dev)->data = data;\n+\t(*eth_dev)->dev_ops = &ops;\n+\t(*eth_dev)->pci_dev = pci_dev;\n+\t(*eth_dev)->driver = &rte_pcap_pmd;\n+\n+\treturn 0;\n+\n+error: \n+\trte_free(data);\n+\trte_free(pci_dev);\n+\trte_free(*internals);\n+\n+\treturn -1;\n+}\n+\n+static int\n+rte_eth_from_pcaps_n_dumpers(const char *name,\n+\t\tstruct rx_pcaps *rx_queues,\n+\t\tconst unsigned nb_rx_queues,\n+\t\tstruct tx_pcaps *tx_queues,\n+\t\tconst unsigned nb_tx_queues,\n+\t\tconst unsigned numa_node,\n+\t\tstruct rte_kvargs *kvlist)\n+{\n+\tstruct pmd_internals *internals = NULL;\n+\tstruct rte_eth_dev *eth_dev = NULL;\n+\tunsigned i;\n+\n+\t/* do some parameter checking */\n+\tif (rx_queues == NULL && nb_rx_queues > 0)\n+\t\treturn -1;\n+\tif (tx_queues == NULL && nb_tx_queues > 0)\n+\t\treturn -1;\n+\n+\tif (rte_pmd_init_internals(name, nb_rx_queues, nb_tx_queues, numa_node,\n+\t\t\t&internals, &eth_dev, kvlist) < 0)\n+\t\treturn -1;\n+\n+\tfor (i = 0; i < nb_rx_queues; i++) {\n+\t\tinternals->rx_queue[i].pcap = rx_queues->pcaps[i];\n+\t\tsnprintf(internals->rx_queue[i].name,\n+\t\t\tsizeof(internals->rx_queue[i].name), \"%s\",\n+\t\t\trx_queues->names[i]);\n+\t\tsnprintf(internals->rx_queue[i].type,\n+\t\t\tsizeof(internals->rx_queue[i].type), \"%s\",\n+\t\t\trx_queues->types[i]);\n+\t}\n+\tfor (i = 0; i < nb_tx_queues; i++) {\n+\t\tinternals->tx_queue[i].dumper = tx_queues->dumpers[i];\n+\t\tsnprintf(internals->tx_queue[i].name,\n+\t\t\tsizeof(internals->tx_queue[i].name), \"%s\",\n+\t\t\ttx_queues->names[i]);\n+\t\tsnprintf(internals->tx_queue[i].type,\n+\t\t\tsizeof(internals->tx_queue[i].type), \"%s\",\n+\t\t\ttx_queues->types[i]);\n+\t}\n+\n+\t/* using multiple pcaps/interfaces */\n+\tinternals->single_iface = 0;\n+\n+\teth_dev->rx_pkt_burst = eth_pcap_rx;\n+\teth_dev->tx_pkt_burst = eth_pcap_tx_dumper;\n+\n+\treturn 0;\n+}\n+\n+static int\n+rte_eth_from_pcaps(const char *name,\n+\t\tstruct rx_pcaps *rx_queues,\n+\t\tconst unsigned nb_rx_queues,\n+\t\tstruct tx_pcaps *tx_queues,\n+\t\tconst unsigned nb_tx_queues,\n+\t\tconst unsigned numa_node,\n+\t\tstruct rte_kvargs *kvlist,\n+\t\tint single_iface)\n+{\n+\tstruct pmd_internals *internals = NULL;\n+\tstruct rte_eth_dev *eth_dev = NULL;\n+\tunsigned i;\n+\n+\t/* do some parameter checking */\n+\tif (rx_queues == NULL && nb_rx_queues > 0)\n+\t\treturn -1;\n+\tif (tx_queues == NULL && nb_tx_queues > 0)\n+\t\treturn -1;\n+\n+\tif (rte_pmd_init_internals(name, nb_rx_queues, nb_tx_queues, numa_node,\n+\t\t\t&internals, &eth_dev, kvlist) < 0)\n+\t\treturn -1;\n+\n+\tfor (i = 0; i < nb_rx_queues; i++) {\n+\t\tinternals->rx_queue[i].pcap = rx_queues->pcaps[i];\n+\t\tsnprintf(internals->rx_queue[i].name,\n+\t\t\tsizeof(internals->rx_queue[i].name), \"%s\",\n+\t\t\trx_queues->names[i]);\n+\t\tsnprintf(internals->rx_queue[i].type,\n+\t\t\tsizeof(internals->rx_queue[i].type), \"%s\",\n+\t\t\trx_queues->types[i]);\n+\t}\n+\tfor (i = 0; i < nb_tx_queues; i++) {\n+\t\tinternals->tx_queue[i].dumper = tx_queues->dumpers[i];\n+\t\tsnprintf(internals->tx_queue[i].name,\n+\t\t\tsizeof(internals->tx_queue[i].name), \"%s\",\n+\t\t\ttx_queues->names[i]);\n+\t\tsnprintf(internals->tx_queue[i].type,\n+\t\t\tsizeof(internals->tx_queue[i].type), \"%s\",\n+\t\t\ttx_queues->types[i]);\n+\t}\n+\n+\t/* store wether we are using a single interface for rx/tx or not */\n+\tinternals->single_iface = single_iface;\n+\n+\teth_dev->rx_pkt_burst = eth_pcap_rx;\n+\teth_dev->tx_pkt_burst = eth_pcap_tx;\n+\n+\treturn 0;\n+}\n+\n+\n+static int\n+rte_pmd_pcap_devinit(const char *name, const char *params)\n+{\n+\tunsigned numa_node, using_dumpers = 0;\n+\tint ret;\n+\tstruct rte_kvargs *kvlist;\n+\tstruct rx_pcaps pcaps;\n+\tstruct tx_pcaps dumpers;\n+\n+\tRTE_LOG(INFO, PMD, \"Initializing pmd_pcap for %s\\n\", name);\n+\n+\tnuma_node = rte_socket_id();\n+\n+\tgettimeofday(&start_time, NULL);\n+\tstart_cycles = rte_get_timer_cycles();\n+\thz = rte_get_timer_hz();\n+\n+\tkvlist = rte_kvargs_parse(params, valid_arguments);\n+\tif (kvlist == NULL)\n+\t\treturn -1;\n+\n+\t/*\n+\t * If iface argument is passed we open the NICs and use them for\n+\t * reading / writing\n+\t */\n+\tif (rte_kvargs_count(kvlist, ETH_PCAP_IFACE_ARG) == 1) {\n+\n+\t\tret = rte_kvargs_process(kvlist, ETH_PCAP_IFACE_ARG,\n+\t\t\t\t&open_rx_tx_iface, &pcaps);\n+\t\tif (ret < 0)\n+\t\t\tgoto free_kvlist;\n+\t\tdumpers.pcaps[0] = pcaps.pcaps[0];\n+\t\tdumpers.names[0] = pcaps.names[0];\n+\t\tdumpers.types[0] = pcaps.types[0];\n+\t\tret = rte_eth_from_pcaps(name, &pcaps, 1, &dumpers, 1,\n+\t\t\t\tnuma_node, kvlist, 1);\n+\t\tgoto free_kvlist;\n+\t}\n+\n+\t/*\n+\t * We check whether we want to open a RX stream from a real NIC or a\n+\t * pcap file\n+\t */\n+\tif ((pcaps.num_of_rx = rte_kvargs_count(kvlist, ETH_PCAP_RX_PCAP_ARG))) {\n+\t\tret = rte_kvargs_process(kvlist, ETH_PCAP_RX_PCAP_ARG,\n+\t\t\t\t&open_rx_pcap, &pcaps);\n+\t} else {\n+\t\tpcaps.num_of_rx = rte_kvargs_count(kvlist,\n+\t\t\t\tETH_PCAP_RX_IFACE_ARG);\n+\t\tret = rte_kvargs_process(kvlist, ETH_PCAP_RX_IFACE_ARG,\n+\t\t\t\t&open_rx_iface, &pcaps);\n+\t}\n+\n+\tif (ret < 0)\n+\t\tgoto free_kvlist;\n+\n+\t/*\n+\t * We check whether we want to open a TX stream to a real NIC or a\n+\t * pcap file\n+\t */\n+\tif ((dumpers.num_of_tx = rte_kvargs_count(kvlist,\n+\t\t\tETH_PCAP_TX_PCAP_ARG))) {\n+\t\tret = rte_kvargs_process(kvlist, ETH_PCAP_TX_PCAP_ARG,\n+\t\t\t\t&open_tx_pcap, &dumpers);\n+\t\tusing_dumpers = 1;\n+\t} else {\n+\t\tdumpers.num_of_tx = rte_kvargs_count(kvlist,\n+\t\t\t\tETH_PCAP_TX_IFACE_ARG);\n+\t\tret = rte_kvargs_process(kvlist, ETH_PCAP_TX_IFACE_ARG,\n+\t\t\t\t&open_tx_iface, &dumpers);\n+\t}\n+\n+\tif (ret < 0)\n+\t\tgoto free_kvlist;\n+\n+\tif (using_dumpers)\n+\t\tret = rte_eth_from_pcaps_n_dumpers(name, &pcaps, pcaps.num_of_rx,\n+\t\t\t\t&dumpers, dumpers.num_of_tx, numa_node, kvlist);\n+\telse\n+\t\tret = rte_eth_from_pcaps(name, &pcaps, pcaps.num_of_rx, &dumpers,\n+\t\t\tdumpers.num_of_tx, numa_node, kvlist, 0);\n+\n+free_kvlist:\n+\trte_kvargs_free(kvlist);\n+\treturn ret;\n+}\n+\n+static int\n+rte_pmd_pcap_devuninit(const char *name)\n+{\n+\tstruct rte_eth_dev *eth_dev = NULL;\n+\n+\tRTE_LOG(INFO, PMD, \"Closing pcap ethdev on numa socket %u\\n\",\n+\t\t\trte_socket_id());\n+\n+\tif (name == NULL)\n+\t\treturn -1;\n+\n+\t/* reserve an ethdev entry */\n+\teth_dev = rte_eth_dev_allocated(name);\n+\tif (eth_dev == NULL)\n+\t\treturn -1;\n+\n+\trte_free(eth_dev->data->dev_private);\n+\trte_free(eth_dev->data);\n+\trte_free(eth_dev->pci_dev);\n+\n+\trte_eth_dev_release_port(eth_dev);\n+\n+\treturn 0;\n+}\n+\n+static struct rte_driver pmd_pcap_drv = {\n+\t.name = \"eth_pcap\",\n+\t.type = PMD_VDEV,\n+\t.init = rte_pmd_pcap_devinit,\n+\t.uninit = rte_pmd_pcap_devuninit,\n+};\n+\n+PMD_REGISTER_DRIVER(pmd_pcap_drv);\ndiff --git a/drivers/net/pcap/rte_pmd_pcap_version.map b/drivers/net/pcap/rte_pmd_pcap_version.map\nnew file mode 100644\nindex 0000000..ef35398\n--- /dev/null\n+++ b/drivers/net/pcap/rte_pmd_pcap_version.map\n@@ -0,0 +1,4 @@\n+DPDK_2.0 {\n+\n+\tlocal: *;\n+};\ndiff --git a/lib/Makefile b/lib/Makefile\nindex d4533dc..e63f1fe 100644\n--- a/lib/Makefile\n+++ b/lib/Makefile\n@@ -42,7 +42,6 @@ DIRS-$(CONFIG_RTE_LIBRTE_CFGFILE) += librte_cfgfile\n DIRS-$(CONFIG_RTE_LIBRTE_CMDLINE) += librte_cmdline\n DIRS-$(CONFIG_RTE_LIBRTE_ETHER) += librte_ether\n DIRS-$(CONFIG_RTE_LIBRTE_PMD_RING) += librte_pmd_ring\n-DIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += librte_pmd_pcap\n DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += librte_pmd_virtio\n DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3\n DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt\ndiff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile\nindex 2357cfa..c2fe933 100644\n--- a/lib/librte_eal/bsdapp/eal/Makefile\n+++ b/lib/librte_eal/bsdapp/eal/Makefile\n@@ -1,6 +1,6 @@\n #   BSD LICENSE\n #\n-#   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+#   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.\n #   All rights reserved.\n #\n #   Redistribution and use in source and binary forms, with or without\n@@ -43,7 +43,7 @@ CFLAGS += -I$(RTE_SDK)/lib/librte_mempool\n CFLAGS += -I$(RTE_SDK)/lib/librte_malloc\n CFLAGS += -I$(RTE_SDK)/lib/librte_ether\n CFLAGS += -I$(RTE_SDK)/lib/librte_pmd_ring\n-CFLAGS += -I$(RTE_SDK)/lib/librte_pmd_pcap\n+CFLAGS += -I$(RTE_SDK)/drivers/net/pcap\n CFLAGS += $(WERROR_FLAGS) -O3\n \n EXPORT_MAP := rte_eal_version.map\ndiff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile\nindex 7d3cf66..fdb3656 100644\n--- a/lib/librte_eal/linuxapp/eal/Makefile\n+++ b/lib/librte_eal/linuxapp/eal/Makefile\n@@ -48,7 +48,7 @@ CFLAGS += -I$(RTE_SDK)/lib/librte_malloc\n CFLAGS += -I$(RTE_SDK)/lib/librte_ether\n CFLAGS += -I$(RTE_SDK)/lib/librte_ivshmem\n CFLAGS += -I$(RTE_SDK)/lib/librte_pmd_ring\n-CFLAGS += -I$(RTE_SDK)/lib/librte_pmd_pcap\n+CFLAGS += -I$(RTE_SDK)/drivers/net/pcap\n CFLAGS += -I$(RTE_SDK)/drivers/net/af_packet\n CFLAGS += -I$(RTE_SDK)/lib/librte_pmd_xenvirt\n CFLAGS += $(WERROR_FLAGS) -O3\ndiff --git a/lib/librte_pmd_pcap/Makefile b/lib/librte_pmd_pcap/Makefile\ndeleted file mode 100644\nindex 0775dbc..0000000\n--- a/lib/librte_pmd_pcap/Makefile\n+++ /dev/null\n@@ -1,63 +0,0 @@\n-#   BSD LICENSE\n-#\n-#   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n-#   Copyright(c) 2014 6WIND S.A.\n-#   All rights reserved.\n-#\n-#   Redistribution and use in source and binary forms, with or without\n-#   modification, are permitted provided that the following conditions\n-#   are met:\n-#\n-#     * Redistributions of source code must retain the above copyright\n-#       notice, this list of conditions and the following disclaimer.\n-#     * Redistributions in binary form must reproduce the above copyright\n-#       notice, this list of conditions and the following disclaimer in\n-#       the documentation and/or other materials provided with the\n-#       distribution.\n-#     * Neither the name of Intel Corporation nor the names of its\n-#       contributors may be used to endorse or promote products derived\n-#       from this software without specific prior written permission.\n-#\n-#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n-#   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n-#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n-#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n-#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n-#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n-#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n-#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n-#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n-#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n-#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n-\n-include $(RTE_SDK)/mk/rte.vars.mk\n-\n-#\n-# library name\n-#\n-LIB = librte_pmd_pcap.a\n-\n-CFLAGS += -O3\n-CFLAGS += $(WERROR_FLAGS)\n-\n-EXPORT_MAP := rte_pmd_pcap_version.map\n-\n-LIBABIVER := 1\n-\n-#\n-# all source are stored in SRCS-y\n-#\n-SRCS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += rte_eth_pcap.c\n-\n-#\n-# Export include files\n-#\n-SYMLINK-y-include +=\n-\n-# this lib depends upon:\n-DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += lib/librte_mbuf\n-DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += lib/librte_ether\n-DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += lib/librte_malloc\n-DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += lib/librte_kvargs\n-\n-include $(RTE_SDK)/mk/rte.lib.mk\ndiff --git a/lib/librte_pmd_pcap/rte_eth_pcap.c b/lib/librte_pmd_pcap/rte_eth_pcap.c\ndeleted file mode 100644\nindex ff9b534..0000000\n--- a/lib/librte_pmd_pcap/rte_eth_pcap.c\n+++ /dev/null\n@@ -1,994 +0,0 @@\n-/*-\n- *   BSD LICENSE\n- *\n- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n- *   Copyright(c) 2014 6WIND S.A.\n- *   All rights reserved.\n- *\n- *   Redistribution and use in source and binary forms, with or without\n- *   modification, are permitted provided that the following conditions\n- *   are met:\n- *\n- *     * Redistributions of source code must retain the above copyright\n- *       notice, this list of conditions and the following disclaimer.\n- *     * Redistributions in binary form must reproduce the above copyright\n- *       notice, this list of conditions and the following disclaimer in\n- *       the documentation and/or other materials provided with the\n- *       distribution.\n- *     * Neither the name of Intel Corporation nor the names of its\n- *       contributors may be used to endorse or promote products derived\n- *       from this software without specific prior written permission.\n- *\n- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n- *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n- */\n-\n-#include <time.h>\n-#include <rte_mbuf.h>\n-#include <rte_ethdev.h>\n-#include <rte_malloc.h>\n-#include <rte_memcpy.h>\n-#include <rte_string_fns.h>\n-#include <rte_cycles.h>\n-#include <rte_kvargs.h>\n-#include <rte_dev.h>\n-\n-#include <net/if.h>\n-\n-#include <pcap.h>\n-\n-#define RTE_ETH_PCAP_SNAPSHOT_LEN 65535\n-#define RTE_ETH_PCAP_SNAPLEN 4096\n-#define RTE_ETH_PCAP_PROMISC 1\n-#define RTE_ETH_PCAP_TIMEOUT -1\n-#define ETH_PCAP_RX_PCAP_ARG  \"rx_pcap\"\n-#define ETH_PCAP_TX_PCAP_ARG  \"tx_pcap\"\n-#define ETH_PCAP_RX_IFACE_ARG \"rx_iface\"\n-#define ETH_PCAP_TX_IFACE_ARG \"tx_iface\"\n-#define ETH_PCAP_IFACE_ARG    \"iface\"\n-\n-#define ETH_PCAP_ARG_MAXLEN\t64\n-\n-static char errbuf[PCAP_ERRBUF_SIZE];\n-static struct timeval start_time;\n-static uint64_t start_cycles;\n-static uint64_t hz;\n-\n-struct pcap_rx_queue {\n-\tpcap_t *pcap;\n-\tuint8_t in_port;\n-\tstruct rte_mempool *mb_pool;\n-\tvolatile unsigned long rx_pkts;\n-\tvolatile unsigned long err_pkts;\n-\tchar name[PATH_MAX];\n-\tchar type[ETH_PCAP_ARG_MAXLEN];\n-};\n-\n-struct pcap_tx_queue {\n-\tpcap_dumper_t *dumper;\n-\tpcap_t *pcap;\n-\tvolatile unsigned long tx_pkts;\n-\tvolatile unsigned long err_pkts;\n-\tchar name[PATH_MAX];\n-\tchar type[ETH_PCAP_ARG_MAXLEN];\n-};\n-\n-struct rx_pcaps {\n-\tunsigned num_of_rx;\n-\tpcap_t *pcaps[RTE_PMD_RING_MAX_RX_RINGS];\n-\tconst char *names[RTE_PMD_RING_MAX_RX_RINGS];\n-\tconst char *types[RTE_PMD_RING_MAX_RX_RINGS];\n-};\n-\n-struct tx_pcaps {\n-\tunsigned num_of_tx;\n-\tpcap_dumper_t *dumpers[RTE_PMD_RING_MAX_TX_RINGS];\n-\tpcap_t *pcaps[RTE_PMD_RING_MAX_RX_RINGS];\n-\tconst char *names[RTE_PMD_RING_MAX_RX_RINGS];\n-\tconst char *types[RTE_PMD_RING_MAX_RX_RINGS];\n-};\n-\n-struct pmd_internals {\n-\tstruct pcap_rx_queue rx_queue[RTE_PMD_RING_MAX_RX_RINGS];\n-\tstruct pcap_tx_queue tx_queue[RTE_PMD_RING_MAX_TX_RINGS];\n-\tunsigned nb_rx_queues;\n-\tunsigned nb_tx_queues;\n-\tint if_index;\n-\tint single_iface;\n-};\n-\n-const char *valid_arguments[] = {\n-\tETH_PCAP_RX_PCAP_ARG,\n-\tETH_PCAP_TX_PCAP_ARG,\n-\tETH_PCAP_RX_IFACE_ARG,\n-\tETH_PCAP_TX_IFACE_ARG,\n-\tETH_PCAP_IFACE_ARG,\n-\tNULL\n-};\n-\n-static int open_single_tx_pcap(const char *pcap_filename, pcap_dumper_t **dumper);\n-static int open_single_rx_pcap(const char *pcap_filename, pcap_t **pcap);\n-static int open_single_iface(const char *iface, pcap_t **pcap);\n-\n-static struct ether_addr eth_addr = { .addr_bytes = { 0, 0, 0, 0x1, 0x2, 0x3 } };\n-static const char *drivername = \"Pcap PMD\";\n-static struct rte_eth_link pmd_link = {\n-\t\t.link_speed = 10000,\n-\t\t.link_duplex = ETH_LINK_FULL_DUPLEX,\n-\t\t.link_status = 0\n-};\n-\n-\n-static uint16_t\n-eth_pcap_rx(void *queue,\n-\t\tstruct rte_mbuf **bufs,\n-\t\tuint16_t nb_pkts)\n-{\n-\tunsigned i;\n-\tstruct pcap_pkthdr header;\n-\tconst u_char *packet;\n-\tstruct rte_mbuf *mbuf;\n-\tstruct pcap_rx_queue *pcap_q = queue;\n-\tuint16_t num_rx = 0;\n-\tuint16_t buf_size;\n-\n-\tif (unlikely(pcap_q->pcap == NULL || nb_pkts == 0))\n-\t\treturn 0;\n-\n-\t/* Reads the given number of packets from the pcap file one by one\n-\t * and copies the packet data into a newly allocated mbuf to return.\n-\t */\n-\tfor (i = 0; i < nb_pkts; i++) {\n-\t\t/* Get the next PCAP packet */\n-\t\tpacket = pcap_next(pcap_q->pcap, &header);\n-\t\tif (unlikely(packet == NULL))\n-\t\t\tbreak;\n-\t\telse\n-\t\t\tmbuf = rte_pktmbuf_alloc(pcap_q->mb_pool);\n-\t\tif (unlikely(mbuf == NULL))\n-\t\t\tbreak;\n-\n-\t\t/* Now get the space available for data in the mbuf */\n-\t\tbuf_size = (uint16_t)(rte_pktmbuf_data_room_size(pcap_q->mb_pool) -\n-\t\t\t\tRTE_PKTMBUF_HEADROOM);\n-\n-\t\tif (header.len <= buf_size) {\n-\t\t\t/* pcap packet will fit in the mbuf, go ahead and copy */\n-\t\t\trte_memcpy(rte_pktmbuf_mtod(mbuf, void *), packet,\n-\t\t\t\t\theader.len);\n-\t\t\tmbuf->data_len = (uint16_t)header.len;\n-\t\t\tmbuf->pkt_len = mbuf->data_len;\n-\t\t\tmbuf->port = pcap_q->in_port;\n-\t\t\tbufs[num_rx] = mbuf;\n-\t\t\tnum_rx++;\n-\t\t} else {\n-\t\t\t/* pcap packet will not fit in the mbuf, so drop packet */\n-\t\t\tRTE_LOG(ERR, PMD,\n-\t\t\t\t\t\"PCAP packet %d bytes will not fit in mbuf (%d bytes)\\n\",\n-\t\t\t\t\theader.len, buf_size);\n-\t\t\trte_pktmbuf_free(mbuf);\n-\t\t}\n-\t}\n-\tpcap_q->rx_pkts += num_rx;\n-\treturn num_rx;\n-}\n-\n-static inline void\n-calculate_timestamp(struct timeval *ts) {\n-\tuint64_t cycles;\n-\tstruct timeval cur_time;\n-\n-\tcycles = rte_get_timer_cycles() - start_cycles;\n-\tcur_time.tv_sec = cycles / hz;\n-\tcur_time.tv_usec = (cycles % hz) * 10e6 / hz;\n-\ttimeradd(&start_time, &cur_time, ts);\n-}\n-\n-/*\n- * Callback to handle writing packets to a pcap file.\n- */\n-static uint16_t\n-eth_pcap_tx_dumper(void *queue,\n-\t\tstruct rte_mbuf **bufs,\n-\t\tuint16_t nb_pkts)\n-{\n-\tunsigned i;\n-\tstruct rte_mbuf *mbuf;\n-\tstruct pcap_tx_queue *dumper_q = queue;\n-\tuint16_t num_tx = 0;\n-\tstruct pcap_pkthdr header;\n-\n-\tif (dumper_q->dumper == NULL || nb_pkts == 0)\n-\t\treturn 0;\n-\n-\t/* writes the nb_pkts packets to the previously opened pcap file dumper */\n-\tfor (i = 0; i < nb_pkts; i++) {\n-\t\tmbuf = bufs[i];\n-\t\tcalculate_timestamp(&header.ts);\n-\t\theader.len = mbuf->data_len;\n-\t\theader.caplen = header.len;\n-\t\tpcap_dump((u_char *)dumper_q->dumper, &header,\n-\t\t\t\trte_pktmbuf_mtod(mbuf, void*));\n-\t\trte_pktmbuf_free(mbuf);\n-\t\tnum_tx++;\n-\t}\n-\n-\t/*\n-\t * Since there's no place to hook a callback when the forwarding\n-\t * process stops and to make sure the pcap file is actually written,\n-\t * we flush the pcap dumper within each burst.\n-\t */\n-\tpcap_dump_flush(dumper_q->dumper);\n-\tdumper_q->tx_pkts += num_tx;\n-\tdumper_q->err_pkts += nb_pkts - num_tx;\n-\treturn num_tx;\n-}\n-\n-/*\n- * Callback to handle sending packets through a real NIC.\n- */\n-static uint16_t\n-eth_pcap_tx(void *queue,\n-\t\tstruct rte_mbuf **bufs,\n-\t\tuint16_t nb_pkts)\n-{\n-\tunsigned i;\n-\tint ret;\n-\tstruct rte_mbuf *mbuf;\n-\tstruct pcap_tx_queue *tx_queue = queue;\n-\tuint16_t num_tx = 0;\n-\n-\tif (unlikely(nb_pkts == 0 || tx_queue->pcap == NULL))\n-\t\treturn 0;\n-\n-\tfor (i = 0; i < nb_pkts; i++) {\n-\t\tmbuf = bufs[i];\n-\t\tret = pcap_sendpacket(tx_queue->pcap,\n-\t\t\t\trte_pktmbuf_mtod(mbuf, u_char *),\n-\t\t\t\tmbuf->data_len);\n-\t\tif (unlikely(ret != 0))\n-\t\t\tbreak;\n-\t\tnum_tx++;\n-\t\trte_pktmbuf_free(mbuf);\n-\t}\n-\n-\ttx_queue->tx_pkts += num_tx;\n-\ttx_queue->err_pkts += nb_pkts - num_tx;\n-\treturn num_tx;\n-}\n-\n-static int\n-eth_dev_start(struct rte_eth_dev *dev)\n-{\n-\tunsigned i;\n-\tstruct pmd_internals *internals = dev->data->dev_private;\n-\tstruct pcap_tx_queue *tx;\n-\tstruct pcap_rx_queue *rx;\n-\n-\t/* Special iface case. Single pcap is open and shared between tx/rx. */\n-\tif (internals->single_iface) {\n-\t\ttx = &internals->tx_queue[0];\n-\t\trx = &internals->rx_queue[0];\n-\n-\t\tif (!tx->pcap && strcmp(tx->type, ETH_PCAP_IFACE_ARG) == 0) {\n-\t\t\tif (open_single_iface(tx->name, &tx->pcap) < 0)\n-\t\t\t\treturn -1;\n-\t\t\trx->pcap = tx->pcap;\n-\t\t}\n-\t\tgoto status_up;\n-\t}\n-\n-\t/* If not open already, open tx pcaps/dumpers */\n-\tfor (i = 0; i < internals->nb_tx_queues; i++) {\n-\t\ttx = &internals->tx_queue[i];\n-\n-\t\tif (!tx->dumper && strcmp(tx->type, ETH_PCAP_TX_PCAP_ARG) == 0) {\n-\t\t\tif (open_single_tx_pcap(tx->name, &tx->dumper) < 0)\n-\t\t\t\treturn -1;\n-\t\t}\n-\n-\t\telse if (!tx->pcap && strcmp(tx->type, ETH_PCAP_TX_IFACE_ARG) == 0) {\n-\t\t\tif (open_single_iface(tx->name, &tx->pcap) < 0)\n-\t\t\t\treturn -1;\n-\t\t}\n-\t}\n-\n-\t/* If not open already, open rx pcaps */\n-\tfor (i = 0; i < internals->nb_rx_queues; i++) {\n-\t\trx = &internals->rx_queue[i];\n-\n-\t\tif (rx->pcap != NULL)\n-\t\t\tcontinue;\n-\n-\t\tif (strcmp(rx->type, ETH_PCAP_RX_PCAP_ARG) == 0) {\n-\t\t\tif (open_single_rx_pcap(rx->name, &rx->pcap) < 0)\n-\t\t\t\treturn -1;\n-\t\t}\n-\n-\t\telse if (strcmp(rx->type, ETH_PCAP_RX_IFACE_ARG) == 0) {\n-\t\t\tif (open_single_iface(rx->name, &rx->pcap) < 0)\n-\t\t\t\treturn -1;\n-\t\t}\n-\t}\n-\n-status_up:\n-\n-\tdev->data->dev_link.link_status = 1;\n-\treturn 0;\n-}\n-\n-/*\n- * This function gets called when the current port gets stopped.\n- * Is the only place for us to close all the tx streams dumpers.\n- * If not called the dumpers will be flushed within each tx burst.\n- */\n-static void\n-eth_dev_stop(struct rte_eth_dev *dev)\n-{\n-\tunsigned i;\n-\tstruct pmd_internals *internals = dev->data->dev_private;\n-\tstruct pcap_tx_queue *tx;\n-\tstruct pcap_rx_queue *rx;\n-\n-\t/* Special iface case. Single pcap is open and shared between tx/rx. */\n-\tif (internals->single_iface) {\n-\t\ttx = &internals->tx_queue[0];\n-\t\trx = &internals->rx_queue[0];\n-\t\tpcap_close(tx->pcap);\n-\t\ttx->pcap = NULL;\n-\t\trx->pcap = NULL;\n-\t\tgoto status_down;\n-\t}\n-\n-\tfor (i = 0; i < internals->nb_tx_queues; i++) {\n-\t\ttx = &internals->tx_queue[i];\n-\n-\t\tif (tx->dumper != NULL) {\n-\t\t\tpcap_dump_close(tx->dumper);\n-\t\t\ttx->dumper = NULL;\n-\t\t}\n-\n-\t\tif (tx->pcap != NULL) {\n-\t\t\tpcap_close(tx->pcap);\n-\t\t\ttx->pcap = NULL;\n-\t\t}\n-\t}\n-\n-\tfor (i = 0; i < internals->nb_rx_queues; i++) {\n-\t\trx = &internals->rx_queue[i];\n-\n-\t\tif (rx->pcap != NULL) {\n-\t\t\tpcap_close(rx->pcap);\n-\t\t\trx->pcap = NULL;\n-\t\t}\n-\t}\n-\n-status_down:\n-\tdev->data->dev_link.link_status = 0;\n-}\n-\n-static int\n-eth_dev_configure(struct rte_eth_dev *dev __rte_unused)\n-{\n-\treturn 0;\n-}\n-\n-static void\n-eth_dev_info(struct rte_eth_dev *dev,\n-\t\tstruct rte_eth_dev_info *dev_info)\n-{\n-\tstruct pmd_internals *internals = dev->data->dev_private;\n-\tdev_info->driver_name = drivername;\n-\tdev_info->if_index = internals->if_index;\n-\tdev_info->max_mac_addrs = 1;\n-\tdev_info->max_rx_pktlen = (uint32_t) -1;\n-\tdev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;\n-\tdev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;\n-\tdev_info->min_rx_bufsize = 0;\n-\tdev_info->pci_dev = NULL;\n-}\n-\n-static void\n-eth_stats_get(struct rte_eth_dev *dev,\n-\t\tstruct rte_eth_stats *igb_stats)\n-{\n-\tunsigned i;\n-\tunsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;\n-\tconst struct pmd_internals *internal = dev->data->dev_private;\n-\n-\tfor (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS && i < internal->nb_rx_queues;\n-\t\t\ti++) {\n-\t\tigb_stats->q_ipackets[i] = internal->rx_queue[i].rx_pkts;\n-\t\trx_total += igb_stats->q_ipackets[i];\n-\t}\n-\n-\tfor (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS && i < internal->nb_tx_queues;\n-\t\t\ti++) {\n-\t\tigb_stats->q_opackets[i] = internal->tx_queue[i].tx_pkts;\n-\t\tigb_stats->q_errors[i] = internal->tx_queue[i].err_pkts;\n-\t\ttx_total += igb_stats->q_opackets[i];\n-\t\ttx_err_total += igb_stats->q_errors[i];\n-\t}\n-\n-\tigb_stats->ipackets = rx_total;\n-\tigb_stats->opackets = tx_total;\n-\tigb_stats->oerrors = tx_err_total;\n-}\n-\n-static void\n-eth_stats_reset(struct rte_eth_dev *dev)\n-{\n-\tunsigned i;\n-\tstruct pmd_internals *internal = dev->data->dev_private;\n-\tfor (i = 0; i < internal->nb_rx_queues; i++)\n-\t\tinternal->rx_queue[i].rx_pkts = 0;\n-\tfor (i = 0; i < internal->nb_tx_queues; i++) {\n-\t\tinternal->tx_queue[i].tx_pkts = 0;\n-\t\tinternal->tx_queue[i].err_pkts = 0;\n-\t}\n-}\n-\n-static void\n-eth_dev_close(struct rte_eth_dev *dev __rte_unused)\n-{\n-}\n-\n-static void\n-eth_queue_release(void *q __rte_unused)\n-{\n-}\n-\n-static int\n-eth_link_update(struct rte_eth_dev *dev __rte_unused,\n-\t\tint wait_to_complete __rte_unused)\n-{\n-\treturn 0;\n-}\n-\n-static int\n-eth_rx_queue_setup(struct rte_eth_dev *dev,\n-\t\tuint16_t rx_queue_id,\n-\t\tuint16_t nb_rx_desc __rte_unused,\n-\t\tunsigned int socket_id __rte_unused,\n-\t\tconst struct rte_eth_rxconf *rx_conf __rte_unused,\n-\t\tstruct rte_mempool *mb_pool)\n-{\n-\tstruct pmd_internals *internals = dev->data->dev_private;\n-\tstruct pcap_rx_queue *pcap_q = &internals->rx_queue[rx_queue_id];\n-\tpcap_q->mb_pool = mb_pool;\n-\tdev->data->rx_queues[rx_queue_id] = pcap_q;\n-\tpcap_q->in_port = dev->data->port_id;\n-\treturn 0;\n-}\n-\n-static int\n-eth_tx_queue_setup(struct rte_eth_dev *dev,\n-\t\tuint16_t tx_queue_id,\n-\t\tuint16_t nb_tx_desc __rte_unused,\n-\t\tunsigned int socket_id __rte_unused,\n-\t\tconst struct rte_eth_txconf *tx_conf __rte_unused)\n-{\n-\n-\tstruct pmd_internals *internals = dev->data->dev_private;\n-\tdev->data->tx_queues[tx_queue_id] = &internals->tx_queue[tx_queue_id];\n-\treturn 0;\n-}\n-\n-static const struct eth_dev_ops ops = {\n-\t.dev_start = eth_dev_start,\n-\t.dev_stop =\teth_dev_stop,\n-\t.dev_close = eth_dev_close,\n-\t.dev_configure = eth_dev_configure,\n-\t.dev_infos_get = eth_dev_info,\n-\t.rx_queue_setup = eth_rx_queue_setup,\n-\t.tx_queue_setup = eth_tx_queue_setup,\n-\t.rx_queue_release = eth_queue_release,\n-\t.tx_queue_release = eth_queue_release,\n-\t.link_update = eth_link_update,\n-\t.stats_get = eth_stats_get,\n-\t.stats_reset = eth_stats_reset,\n-};\n-\n-static struct eth_driver rte_pcap_pmd = {\n-\t.pci_drv = {\n-\t\t.name = \"rte_pcap_pmd\",\n-\t\t.drv_flags = RTE_PCI_DRV_DETACHABLE,\n-\t},\n-};\n-\n-/*\n- * Function handler that opens the pcap file for reading a stores a\n- * reference of it for use it later on.\n- */\n-static int\n-open_rx_pcap(const char *key, const char *value, void *extra_args)\n-{\n-\tunsigned i;\n-\tconst char *pcap_filename = value;\n-\tstruct rx_pcaps *pcaps = extra_args;\n-\tpcap_t *pcap = NULL;\n-\n-\tfor (i = 0; i < pcaps->num_of_rx; i++) {\n-\t\tif (open_single_rx_pcap(pcap_filename, &pcap) < 0)\n-\t\t\treturn -1;\n-\n-\t\tpcaps->pcaps[i] = pcap;\n-\t\tpcaps->names[i] = pcap_filename;\n-\t\tpcaps->types[i] = key;\n-\t}\n-\n-\treturn 0;\n-}\n-\n-static int\n-open_single_rx_pcap(const char *pcap_filename, pcap_t **pcap)\n-{\n-\tif ((*pcap = pcap_open_offline(pcap_filename, errbuf)) == NULL) {\n-\t\tRTE_LOG(ERR, PMD, \"Couldn't open %s: %s\\n\", pcap_filename, errbuf);\n-\t\treturn -1;\n-\t}\n-\treturn 0;\n-}\n-\n-/*\n- * Opens a pcap file for writing and stores a reference to it\n- * for use it later on.\n- */\n-static int\n-open_tx_pcap(const char *key, const char *value, void *extra_args)\n-{\n-\tunsigned i;\n-\tconst char *pcap_filename = value;\n-\tstruct tx_pcaps *dumpers = extra_args;\n-\tpcap_dumper_t *dumper;\n-\n-\tfor (i = 0; i < dumpers->num_of_tx; i++) {\n-\t\tif (open_single_tx_pcap(pcap_filename, &dumper) < 0)\n-\t\t\treturn -1;\n-\n-\t\tdumpers->dumpers[i] = dumper;\n-\t\tdumpers->names[i] = pcap_filename;\n-\t\tdumpers->types[i] = key;\n-\t}\n-\n-\treturn 0;\n-}\n-\n-static int\n-open_single_tx_pcap(const char *pcap_filename, pcap_dumper_t **dumper)\n-{\n-\tpcap_t *tx_pcap;\n-\t/*\n-\t * We need to create a dummy empty pcap_t to use it\n-\t * with pcap_dump_open(). We create big enough an Ethernet\n-\t * pcap holder.\n-\t */\n-\n-\tif ((tx_pcap = pcap_open_dead(DLT_EN10MB, RTE_ETH_PCAP_SNAPSHOT_LEN))\n-\t\t\t== NULL) {\n-\t\tRTE_LOG(ERR, PMD, \"Couldn't create dead pcap\\n\");\n-\t\treturn -1;\n-\t}\n-\n-\t/* The dumper is created using the previous pcap_t reference */\n-\tif ((*dumper = pcap_dump_open(tx_pcap, pcap_filename)) == NULL) {\n-\t\tRTE_LOG(ERR, PMD, \"Couldn't open %s for writing.\\n\", pcap_filename);\n-\t\treturn -1;\n-\t}\n-\n-\treturn 0;\n-}\n-\n-/*\n- * pcap_open_live wrapper function\n- */\n-static inline int\n-open_iface_live(const char *iface, pcap_t **pcap) {\n-\t*pcap = pcap_open_live(iface, RTE_ETH_PCAP_SNAPLEN,\n-\t\t\tRTE_ETH_PCAP_PROMISC, RTE_ETH_PCAP_TIMEOUT, errbuf);\n-\n-\tif (*pcap == NULL) {\n-\t\tRTE_LOG(ERR, PMD, \"Couldn't open %s: %s\\n\", iface, errbuf);\n-\t\treturn -1;\n-\t}\n-\treturn 0;\n-}\n-\n-/*\n- * Opens an interface for reading and writing\n- */\n-static inline int\n-open_rx_tx_iface(const char *key, const char *value, void *extra_args)\n-{\n-\tconst char *iface = value;\n-\tstruct rx_pcaps *pcaps = extra_args;\n-\tpcap_t *pcap = NULL;\n-\n-\tif (open_single_iface(iface, &pcap) < 0)\n-\t\treturn -1;\n-\n-\tpcaps->pcaps[0] = pcap;\n-\tpcaps->names[0] = iface;\n-\tpcaps->types[0] = key;\n-\n-\treturn 0;\n-}\n-\n-/*\n- * Opens a NIC for reading packets from it\n- */\n-static inline int\n-open_rx_iface(const char *key, const char *value, void *extra_args)\n-{\n-\tunsigned i;\n-\tconst char *iface = value;\n-\tstruct rx_pcaps *pcaps = extra_args;\n-\tpcap_t *pcap = NULL;\n-\n-\tfor (i = 0; i < pcaps->num_of_rx; i++) {\n-\t\tif (open_single_iface(iface, &pcap) < 0)\n-\t\t\treturn -1;\n-\t\tpcaps->pcaps[i] = pcap;\n-\t\tpcaps->names[i] = iface;\n-\t\tpcaps->types[i] = key;\n-\t}\n-\n-\treturn 0;\n-}\n-\n-/*\n- * Opens a NIC for writing packets to it\n- */\n-static int\n-open_tx_iface(const char *key, const char *value, void *extra_args)\n-{\n-\tunsigned i;\n-\tconst char *iface = value;\n-\tstruct tx_pcaps *pcaps = extra_args;\n-\tpcap_t *pcap;\n-\n-\tfor (i = 0; i < pcaps->num_of_tx; i++) {\n-\t\tif (open_single_iface(iface, &pcap) < 0)\n-\t\t\treturn -1;\n-\t\tpcaps->pcaps[i] = pcap;\n-\t\tpcaps->names[i] = iface;\n-\t\tpcaps->types[i] = key;\n-\t}\n-\n-\treturn 0;\n-}\n-\n-static int\n-open_single_iface(const char *iface, pcap_t **pcap)\n-{\n-\tif (open_iface_live(iface, pcap) < 0) {\n-\t\tRTE_LOG(ERR, PMD, \"Couldn't open interface %s\\n\", iface);\n-\t\treturn -1;\n-\t}\n-\n-\treturn 0;\n-}\n-\n-static int\n-rte_pmd_init_internals(const char *name, const unsigned nb_rx_queues,\n-\t\tconst unsigned nb_tx_queues,\n-\t\tconst unsigned numa_node,\n-\t\tstruct pmd_internals **internals,\n-\t\tstruct rte_eth_dev **eth_dev,\n-\t\tstruct rte_kvargs *kvlist)\n-{\n-\tstruct rte_eth_dev_data *data = NULL;\n-\tstruct rte_pci_device *pci_dev = NULL;\n-\tunsigned k_idx;\n-\tstruct rte_kvargs_pair *pair = NULL;\n-\n-\tfor (k_idx = 0; k_idx < kvlist->count; k_idx++) {\n-\t\tpair = &kvlist->pairs[k_idx];\n-\t\tif (strstr(pair->key, ETH_PCAP_IFACE_ARG) != NULL)\n-\t\t\tbreak;\n-\t}\n-\n-\tRTE_LOG(INFO, PMD,\n-\t\t\t\"Creating pcap-backed ethdev on numa socket %u\\n\", numa_node);\n-\n-\t/* now do all data allocation - for eth_dev structure, dummy pci driver\n-\t * and internal (private) data\n-\t */\n-\tdata = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);\n-\tif (data == NULL)\n-\t\tgoto error;\n-\n-\tpci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);\n-\tif (pci_dev == NULL)\n-\t\tgoto error;\n-\n-\t*internals = rte_zmalloc_socket(name, sizeof(**internals), 0, numa_node);\n-\tif (*internals == NULL)\n-\t\tgoto error;\n-\n-\t/* reserve an ethdev entry */\n-\t*eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL);\n-\tif (*eth_dev == NULL)\n-\t\tgoto error;\n-\n-\t/* check length of device name */\n-\tif ((strlen((*eth_dev)->data->name) + 1) > sizeof(data->name))\n-\t\tgoto error;\n-\n-\t/* now put it all together\n-\t * - store queue data in internals,\n-\t * - store numa_node info in pci_driver\n-\t * - point eth_dev_data to internals and pci_driver\n-\t * - and point eth_dev structure to new eth_dev_data structure\n-\t */\n-\t/* NOTE: we'll replace the data element, of originally allocated eth_dev\n-\t * so the rings are local per-process */\n-\n-\t(*internals)->nb_rx_queues = nb_rx_queues;\n-\t(*internals)->nb_tx_queues = nb_tx_queues;\n-\n-\tif (pair == NULL)\n-\t\t(*internals)->if_index = 0;\n-\telse\n-\t\t(*internals)->if_index = if_nametoindex(pair->value);\n-\n-\tpci_dev->numa_node = numa_node;\n-\n-\tdata->dev_private = *internals;\n-\tdata->port_id = (*eth_dev)->data->port_id;\n-\tsnprintf(data->name, sizeof(data->name), \"%s\", (*eth_dev)->data->name);\n-\tdata->nb_rx_queues = (uint16_t)nb_rx_queues;\n-\tdata->nb_tx_queues = (uint16_t)nb_tx_queues;\n-\tdata->dev_link = pmd_link;\n-\tdata->mac_addrs = &eth_addr;\n-\tstrncpy(data->name,\n-\t\t(*eth_dev)->data->name, strlen((*eth_dev)->data->name));\n-\n-\t(*eth_dev)->data = data;\n-\t(*eth_dev)->dev_ops = &ops;\n-\t(*eth_dev)->pci_dev = pci_dev;\n-\t(*eth_dev)->driver = &rte_pcap_pmd;\n-\n-\treturn 0;\n-\n-error: \n-\trte_free(data);\n-\trte_free(pci_dev);\n-\trte_free(*internals);\n-\n-\treturn -1;\n-}\n-\n-static int\n-rte_eth_from_pcaps_n_dumpers(const char *name,\n-\t\tstruct rx_pcaps *rx_queues,\n-\t\tconst unsigned nb_rx_queues,\n-\t\tstruct tx_pcaps *tx_queues,\n-\t\tconst unsigned nb_tx_queues,\n-\t\tconst unsigned numa_node,\n-\t\tstruct rte_kvargs *kvlist)\n-{\n-\tstruct pmd_internals *internals = NULL;\n-\tstruct rte_eth_dev *eth_dev = NULL;\n-\tunsigned i;\n-\n-\t/* do some parameter checking */\n-\tif (rx_queues == NULL && nb_rx_queues > 0)\n-\t\treturn -1;\n-\tif (tx_queues == NULL && nb_tx_queues > 0)\n-\t\treturn -1;\n-\n-\tif (rte_pmd_init_internals(name, nb_rx_queues, nb_tx_queues, numa_node,\n-\t\t\t&internals, &eth_dev, kvlist) < 0)\n-\t\treturn -1;\n-\n-\tfor (i = 0; i < nb_rx_queues; i++) {\n-\t\tinternals->rx_queue[i].pcap = rx_queues->pcaps[i];\n-\t\tsnprintf(internals->rx_queue[i].name,\n-\t\t\tsizeof(internals->rx_queue[i].name), \"%s\",\n-\t\t\trx_queues->names[i]);\n-\t\tsnprintf(internals->rx_queue[i].type,\n-\t\t\tsizeof(internals->rx_queue[i].type), \"%s\",\n-\t\t\trx_queues->types[i]);\n-\t}\n-\tfor (i = 0; i < nb_tx_queues; i++) {\n-\t\tinternals->tx_queue[i].dumper = tx_queues->dumpers[i];\n-\t\tsnprintf(internals->tx_queue[i].name,\n-\t\t\tsizeof(internals->tx_queue[i].name), \"%s\",\n-\t\t\ttx_queues->names[i]);\n-\t\tsnprintf(internals->tx_queue[i].type,\n-\t\t\tsizeof(internals->tx_queue[i].type), \"%s\",\n-\t\t\ttx_queues->types[i]);\n-\t}\n-\n-\t/* using multiple pcaps/interfaces */\n-\tinternals->single_iface = 0;\n-\n-\teth_dev->rx_pkt_burst = eth_pcap_rx;\n-\teth_dev->tx_pkt_burst = eth_pcap_tx_dumper;\n-\n-\treturn 0;\n-}\n-\n-static int\n-rte_eth_from_pcaps(const char *name,\n-\t\tstruct rx_pcaps *rx_queues,\n-\t\tconst unsigned nb_rx_queues,\n-\t\tstruct tx_pcaps *tx_queues,\n-\t\tconst unsigned nb_tx_queues,\n-\t\tconst unsigned numa_node,\n-\t\tstruct rte_kvargs *kvlist,\n-\t\tint single_iface)\n-{\n-\tstruct pmd_internals *internals = NULL;\n-\tstruct rte_eth_dev *eth_dev = NULL;\n-\tunsigned i;\n-\n-\t/* do some parameter checking */\n-\tif (rx_queues == NULL && nb_rx_queues > 0)\n-\t\treturn -1;\n-\tif (tx_queues == NULL && nb_tx_queues > 0)\n-\t\treturn -1;\n-\n-\tif (rte_pmd_init_internals(name, nb_rx_queues, nb_tx_queues, numa_node,\n-\t\t\t&internals, &eth_dev, kvlist) < 0)\n-\t\treturn -1;\n-\n-\tfor (i = 0; i < nb_rx_queues; i++) {\n-\t\tinternals->rx_queue[i].pcap = rx_queues->pcaps[i];\n-\t\tsnprintf(internals->rx_queue[i].name,\n-\t\t\tsizeof(internals->rx_queue[i].name), \"%s\",\n-\t\t\trx_queues->names[i]);\n-\t\tsnprintf(internals->rx_queue[i].type,\n-\t\t\tsizeof(internals->rx_queue[i].type), \"%s\",\n-\t\t\trx_queues->types[i]);\n-\t}\n-\tfor (i = 0; i < nb_tx_queues; i++) {\n-\t\tinternals->tx_queue[i].dumper = tx_queues->dumpers[i];\n-\t\tsnprintf(internals->tx_queue[i].name,\n-\t\t\tsizeof(internals->tx_queue[i].name), \"%s\",\n-\t\t\ttx_queues->names[i]);\n-\t\tsnprintf(internals->tx_queue[i].type,\n-\t\t\tsizeof(internals->tx_queue[i].type), \"%s\",\n-\t\t\ttx_queues->types[i]);\n-\t}\n-\n-\t/* store wether we are using a single interface for rx/tx or not */\n-\tinternals->single_iface = single_iface;\n-\n-\teth_dev->rx_pkt_burst = eth_pcap_rx;\n-\teth_dev->tx_pkt_burst = eth_pcap_tx;\n-\n-\treturn 0;\n-}\n-\n-\n-static int\n-rte_pmd_pcap_devinit(const char *name, const char *params)\n-{\n-\tunsigned numa_node, using_dumpers = 0;\n-\tint ret;\n-\tstruct rte_kvargs *kvlist;\n-\tstruct rx_pcaps pcaps;\n-\tstruct tx_pcaps dumpers;\n-\n-\tRTE_LOG(INFO, PMD, \"Initializing pmd_pcap for %s\\n\", name);\n-\n-\tnuma_node = rte_socket_id();\n-\n-\tgettimeofday(&start_time, NULL);\n-\tstart_cycles = rte_get_timer_cycles();\n-\thz = rte_get_timer_hz();\n-\n-\tkvlist = rte_kvargs_parse(params, valid_arguments);\n-\tif (kvlist == NULL)\n-\t\treturn -1;\n-\n-\t/*\n-\t * If iface argument is passed we open the NICs and use them for\n-\t * reading / writing\n-\t */\n-\tif (rte_kvargs_count(kvlist, ETH_PCAP_IFACE_ARG) == 1) {\n-\n-\t\tret = rte_kvargs_process(kvlist, ETH_PCAP_IFACE_ARG,\n-\t\t\t\t&open_rx_tx_iface, &pcaps);\n-\t\tif (ret < 0)\n-\t\t\tgoto free_kvlist;\n-\t\tdumpers.pcaps[0] = pcaps.pcaps[0];\n-\t\tdumpers.names[0] = pcaps.names[0];\n-\t\tdumpers.types[0] = pcaps.types[0];\n-\t\tret = rte_eth_from_pcaps(name, &pcaps, 1, &dumpers, 1,\n-\t\t\t\tnuma_node, kvlist, 1);\n-\t\tgoto free_kvlist;\n-\t}\n-\n-\t/*\n-\t * We check whether we want to open a RX stream from a real NIC or a\n-\t * pcap file\n-\t */\n-\tif ((pcaps.num_of_rx = rte_kvargs_count(kvlist, ETH_PCAP_RX_PCAP_ARG))) {\n-\t\tret = rte_kvargs_process(kvlist, ETH_PCAP_RX_PCAP_ARG,\n-\t\t\t\t&open_rx_pcap, &pcaps);\n-\t} else {\n-\t\tpcaps.num_of_rx = rte_kvargs_count(kvlist,\n-\t\t\t\tETH_PCAP_RX_IFACE_ARG);\n-\t\tret = rte_kvargs_process(kvlist, ETH_PCAP_RX_IFACE_ARG,\n-\t\t\t\t&open_rx_iface, &pcaps);\n-\t}\n-\n-\tif (ret < 0)\n-\t\tgoto free_kvlist;\n-\n-\t/*\n-\t * We check whether we want to open a TX stream to a real NIC or a\n-\t * pcap file\n-\t */\n-\tif ((dumpers.num_of_tx = rte_kvargs_count(kvlist,\n-\t\t\tETH_PCAP_TX_PCAP_ARG))) {\n-\t\tret = rte_kvargs_process(kvlist, ETH_PCAP_TX_PCAP_ARG,\n-\t\t\t\t&open_tx_pcap, &dumpers);\n-\t\tusing_dumpers = 1;\n-\t} else {\n-\t\tdumpers.num_of_tx = rte_kvargs_count(kvlist,\n-\t\t\t\tETH_PCAP_TX_IFACE_ARG);\n-\t\tret = rte_kvargs_process(kvlist, ETH_PCAP_TX_IFACE_ARG,\n-\t\t\t\t&open_tx_iface, &dumpers);\n-\t}\n-\n-\tif (ret < 0)\n-\t\tgoto free_kvlist;\n-\n-\tif (using_dumpers)\n-\t\tret = rte_eth_from_pcaps_n_dumpers(name, &pcaps, pcaps.num_of_rx,\n-\t\t\t\t&dumpers, dumpers.num_of_tx, numa_node, kvlist);\n-\telse\n-\t\tret = rte_eth_from_pcaps(name, &pcaps, pcaps.num_of_rx, &dumpers,\n-\t\t\tdumpers.num_of_tx, numa_node, kvlist, 0);\n-\n-free_kvlist:\n-\trte_kvargs_free(kvlist);\n-\treturn ret;\n-}\n-\n-static int\n-rte_pmd_pcap_devuninit(const char *name)\n-{\n-\tstruct rte_eth_dev *eth_dev = NULL;\n-\n-\tRTE_LOG(INFO, PMD, \"Closing pcap ethdev on numa socket %u\\n\",\n-\t\t\trte_socket_id());\n-\n-\tif (name == NULL)\n-\t\treturn -1;\n-\n-\t/* reserve an ethdev entry */\n-\teth_dev = rte_eth_dev_allocated(name);\n-\tif (eth_dev == NULL)\n-\t\treturn -1;\n-\n-\trte_free(eth_dev->data->dev_private);\n-\trte_free(eth_dev->data);\n-\trte_free(eth_dev->pci_dev);\n-\n-\trte_eth_dev_release_port(eth_dev);\n-\n-\treturn 0;\n-}\n-\n-static struct rte_driver pmd_pcap_drv = {\n-\t.name = \"eth_pcap\",\n-\t.type = PMD_VDEV,\n-\t.init = rte_pmd_pcap_devinit,\n-\t.uninit = rte_pmd_pcap_devuninit,\n-};\n-\n-PMD_REGISTER_DRIVER(pmd_pcap_drv);\ndiff --git a/lib/librte_pmd_pcap/rte_pmd_pcap_version.map b/lib/librte_pmd_pcap/rte_pmd_pcap_version.map\ndeleted file mode 100644\nindex ef35398..0000000\n--- a/lib/librte_pmd_pcap/rte_pmd_pcap_version.map\n+++ /dev/null\n@@ -1,4 +0,0 @@\n-DPDK_2.0 {\n-\n-\tlocal: *;\n-};\n",
    "prefixes": [
        "dpdk-dev",
        "v2",
        "12/19"
    ]
}