All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] PMD for performance measurement
       [not found] <mukawa@igel.co.jp>
@ 2014-09-19 12:27 ` mukawa-AlSX/UN32fvPDbFq/vQRIQ
       [not found]   ` <1411129659-7132-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  2014-09-30  9:56 ` [PATCH 0/2] PMD for performance measurement mukawa-AlSX/UN32fvPDbFq/vQRIQ
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 60+ messages in thread
From: mukawa-AlSX/UN32fvPDbFq/vQRIQ @ 2014-09-19 12:27 UTC (permalink / raw)
  To: dev-VfR2kkLFssw
  Cc: nakajima.yoshihiro-Zyj7fXuS5i5L9jVzuh4AOg,
	masutani.hitoshi-Zyj7fXuS5i5L9jVzuh4AOg

From: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>

Hi,

I want to measure throughputs like following cases.

- path connected by RING PMDs
- path connected by librte_vhost and virtio-net PMD
- path connected by MEMNIC PMDs
- .....

Is there anyone want to do same thing?

Anyway, I guess those throughputs may be too high for some devices like ixia.
But it's a bit pain to write or fix applications just for measuring.

I guess a PMD like '/dev/null' and testpmd application will help.
This patch set is RFC of a PMD like '/dev/null'.
Please see the first commit of this patch set.


Here is a my plan to use this PMD

+-------------------------------+
|           testpmd1            |
+-------------+------+----------+
| Target PMD1 |      | null PMD |
+---++--------+      +----------+
    ||
    || Target path
    ||
+---++--------+      +----------+
| Target PMD2 |      | null PMD |
+-------------+------+----------+
|           testpmd2            |
+-------------------------------+

The testpmd1 or testpmd2 will start with "start tx_first". It causes huge
transfers.

The result is not thuroughput of PMD1 or PMD2, but throughput
between PMD1 and PMD2. But I guess it's enough to know rough thuroughput.
Also it's nice for measuing that the same environment can be used.

Any suggestions or comments?

Thanks,
Tetsuya

--
Tetsuya Mukawa (1):
  librte_pmd_null: Add null PMD

 config/common_bsdapp               |   5 +
 config/common_linuxapp             |   5 +
 lib/Makefile                       |   1 +
 lib/librte_pmd_null/Makefile       |  58 +++++
 lib/librte_pmd_null/rte_eth_null.c | 474 +++++++++++++++++++++++++++++++++++++
 5 files changed, 543 insertions(+)
 create mode 100644 lib/librte_pmd_null/Makefile
 create mode 100644 lib/librte_pmd_null/rte_eth_null.c

-- 
1.9.1

^ permalink raw reply	[flat|nested] 60+ messages in thread

* [RFC] librte_pmd_null: Add null PMD
       [not found]   ` <1411129659-7132-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2014-09-19 12:27     ` mukawa-AlSX/UN32fvPDbFq/vQRIQ
       [not found]       ` <1411129659-7132-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  0 siblings, 1 reply; 60+ messages in thread
From: mukawa-AlSX/UN32fvPDbFq/vQRIQ @ 2014-09-19 12:27 UTC (permalink / raw)
  To: dev-VfR2kkLFssw
  Cc: nakajima.yoshihiro-Zyj7fXuS5i5L9jVzuh4AOg,
	masutani.hitoshi-Zyj7fXuS5i5L9jVzuh4AOg

From: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>

'null PMD' is a virtual device driver particulary designed to measure
performance of DPDK applications and DPDK PMDs. When an application call rx,
null PMD just allocate mbufs and return those. Also tx, the PMD just free
mbufs.

The PMD has following options.
- size: specify packe size allocated by RX. Default packet size is 64.
- copy: specify 1 or 0 to enable or disable copy while RX and TX.
	Default value is 0(disbaled).
	This option is used for emulating more realistic data transfer.
	Copy size is equal to packet size.

Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
---
 config/common_bsdapp               |   5 +
 config/common_linuxapp             |   5 +
 lib/Makefile                       |   1 +
 lib/librte_pmd_null/Makefile       |  58 +++++
 lib/librte_pmd_null/rte_eth_null.c | 474 +++++++++++++++++++++++++++++++++++++
 5 files changed, 543 insertions(+)
 create mode 100644 lib/librte_pmd_null/Makefile
 create mode 100644 lib/librte_pmd_null/rte_eth_null.c

diff --git a/config/common_bsdapp b/config/common_bsdapp
index 645949f..a86321f 100644
--- a/config/common_bsdapp
+++ b/config/common_bsdapp
@@ -226,6 +226,11 @@ CONFIG_RTE_LIBRTE_PMD_PCAP=y
 CONFIG_RTE_LIBRTE_PMD_BOND=y
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/config/common_linuxapp b/config/common_linuxapp
index 5bee910..e3bd8c0 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -254,6 +254,11 @@ CONFIG_RTE_LIBRTE_PMD_BOND=y
 CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/lib/Makefile b/lib/Makefile
index 10c5bb3..61d6ed1 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -50,6 +50,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += librte_pmd_pcap
 DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += librte_pmd_virtio
 DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt
+DIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += librte_pmd_null
 DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash
 DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm
 DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl
diff --git a/lib/librte_pmd_null/Makefile b/lib/librte_pmd_null/Makefile
new file mode 100644
index 0000000..e017918
--- /dev/null
+++ b/lib/librte_pmd_null/Makefile
@@ -0,0 +1,58 @@
+#   BSD LICENSE
+#
+#   Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
+#   All rights reserved.
+#
+#   Redistribution and use in source and binary forms, with or without
+#   modification, are permitted provided that the following conditions
+#   are met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in
+#       the documentation and/or other materials provided with the
+#       distribution.
+#     * Neither the name of Intel Corporation nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_pmd_null.a
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += rte_eth_null.c
+
+#
+# Export include files
+#
+SYMLINK-y-include +=
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_malloc
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_kvargs
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
new file mode 100644
index 0000000..1a81843
--- /dev/null
+++ b/lib/librte_pmd_null/rte_eth_null.c
@@ -0,0 +1,474 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_dev.h>
+#include <rte_kvargs.h>
+
+#define ETH_NULL_PACKET_SIZE_ARG	"size"
+#define ETH_NULL_PACKET_COPY_ARG	"copy"
+
+static unsigned default_packet_size = 64;
+static unsigned default_packet_copy;
+
+static const char const *valid_arguments[] = {
+	ETH_NULL_PACKET_SIZE_ARG,
+	ETH_NULL_PACKET_COPY_ARG,
+	NULL
+};
+
+struct pmd_internals;
+
+struct null_queue {
+	struct pmd_internals *internals;
+
+	struct rte_mempool *mb_pool;
+	struct rte_mbuf *dummy_packet;
+
+	rte_atomic64_t rx_pkts;
+	rte_atomic64_t tx_pkts;
+	rte_atomic64_t err_pkts;
+};
+
+struct pmd_internals {
+	unsigned packet_size;
+	unsigned packet_copy;
+	unsigned numa_node;
+
+	unsigned nb_rx_queues;
+	unsigned nb_tx_queues;
+
+	struct null_queue rx_null_queues[1];
+	struct null_queue tx_null_queues[1];
+};
+
+
+static struct ether_addr eth_addr = { .addr_bytes = {0} };
+static const char *drivername = "Null PMD";
+static struct rte_eth_link pmd_link = {
+	.link_speed = 10000,
+	.link_duplex = ETH_LINK_FULL_DUPLEX,
+	.link_status = 0
+};
+
+static uint16_t
+eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,
+					packet_size);
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_tx(void *q, struct rte_mbuf **bufs __rte_unused, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+
+	for (i = 0; i < nb_bufs; i++)
+		rte_pktmbuf_free(bufs[i]);
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	for (i = 0; i < nb_bufs; i++) {
+		rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *),
+					packet_size);
+		rte_pktmbuf_free(bufs[i]);
+	}
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static int
+eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; }
+
+static int
+eth_dev_start(struct rte_eth_dev *dev)
+{
+	dev->data->dev_link.link_status = 1;
+	return 0;
+}
+
+static void
+eth_dev_stop(struct rte_eth_dev *dev)
+{
+	dev->data->dev_link.link_status = 0;
+}
+
+static int
+eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+		uint16_t nb_rx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_rxconf *rx_conf __rte_unused,
+		struct rte_mempool *mb_pool __rte_unused)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals = dev->data->dev_private;
+	unsigned packet_size = internals->packet_size;
+
+	if (rx_queue_id != 0)
+			return -ENODEV;
+
+	internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool;
+	dev->data->rx_queues[rx_queue_id] =
+		&internals->rx_null_queues[rx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->rx_null_queues[rx_queue_id].internals = internals;
+	internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+static int
+eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+		uint16_t nb_tx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals = dev->data->dev_private;
+	unsigned packet_size = internals->packet_size;
+
+	if (tx_queue_id != 0)
+			return -ENODEV;
+
+	dev->data->tx_queues[tx_queue_id] =
+		&internals->tx_null_queues[tx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->tx_null_queues[tx_queue_id].internals = internals;
+	internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+
+static void
+eth_dev_info(struct rte_eth_dev *dev,
+		struct rte_eth_dev_info *dev_info)
+{
+	struct pmd_internals *internals = dev->data->dev_private;
+
+	dev_info->driver_name = drivername;
+	dev_info->max_mac_addrs = 1;
+	dev_info->max_rx_pktlen = (uint32_t)-1;
+	dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;
+	dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;
+	dev_info->min_rx_bufsize = 0;
+	dev_info->pci_dev = NULL;
+}
+
+static void
+eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)
+{
+	unsigned i;
+	unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
+	const struct pmd_internals *internal = dev->data->dev_private;
+
+	memset(igb_stats, 0, sizeof(*igb_stats));
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_rx_queues; i++) {
+		igb_stats->q_ipackets[i] =
+			internal->rx_null_queues[i].rx_pkts.cnt;
+		rx_total += igb_stats->q_ipackets[i];
+	}
+
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_tx_queues; i++) {
+		igb_stats->q_opackets[i] =
+			internal->tx_null_queues[i].tx_pkts.cnt;
+		igb_stats->q_errors[i] =
+			internal->tx_null_queues[i].err_pkts.cnt;
+		tx_total += igb_stats->q_opackets[i];
+		tx_err_total += igb_stats->q_errors[i];
+	}
+
+	igb_stats->ipackets = rx_total;
+	igb_stats->opackets = tx_total;
+	igb_stats->oerrors = tx_err_total;
+}
+
+static void
+eth_stats_reset(struct rte_eth_dev *dev)
+{
+	unsigned i;
+	struct pmd_internals *internal = dev->data->dev_private;
+
+	for (i = 0; i < internal->nb_rx_queues; i++)
+		internal->rx_null_queues[i].rx_pkts.cnt = 0;
+	for (i = 0; i < internal->nb_tx_queues; i++) {
+		internal->tx_null_queues[i].tx_pkts.cnt = 0;
+		internal->tx_null_queues[i].err_pkts.cnt = 0;
+	}
+}
+
+static void
+eth_queue_release(void *q __rte_unused) { ; }
+static int
+eth_link_update(struct rte_eth_dev *dev __rte_unused,
+		int wait_to_complete __rte_unused) { return 0; }
+
+static struct eth_dev_ops ops = {
+		.dev_start = eth_dev_start,
+		.dev_stop = eth_dev_stop,
+		.dev_configure = eth_dev_configure,
+		.dev_infos_get = eth_dev_info,
+		.rx_queue_setup = eth_rx_queue_setup,
+		.tx_queue_setup = eth_tx_queue_setup,
+		.rx_queue_release = eth_queue_release,
+		.tx_queue_release = eth_queue_release,
+		.link_update = eth_link_update,
+		.stats_get = eth_stats_get,
+		.stats_reset = eth_stats_reset,
+};
+
+static int
+eth_dev_null_create(const char *name __rte_unused,
+		const unsigned numa_node,
+		unsigned packet_size,
+		unsigned packet_copy)
+{
+	const unsigned nb_rx_queues = 1;
+	const unsigned nb_tx_queues = 1;
+	struct rte_eth_dev_data *data = NULL;
+	struct rte_pci_device *pci_dev = NULL;
+	struct pmd_internals *internals = NULL;
+	struct rte_eth_dev *eth_dev = NULL;
+
+	RTE_LOG(INFO, PMD, "Creating null ethdev on numa socket %u\n",
+			numa_node);
+
+	/* now do all data allocation - for eth_dev structure, dummy pci driver
+	 * and internal (private) data
+	 */
+	data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);
+	if (data == NULL)
+		goto error;
+
+	pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);
+	if (pci_dev == NULL)
+		goto error;
+
+	internals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node);
+	if (internals == NULL)
+		goto error;
+
+	/* reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocate(name);
+	if (eth_dev == NULL)
+		goto error;
+
+	/* now put it all together
+	 * - store queue data in internals,
+	 * - store numa_node info in pci_driver
+	 * - point eth_dev_data to internals and pci_driver
+	 * - and point eth_dev structure to new eth_dev_data structure
+	 */
+	/* NOTE: we'll replace the data element, of originally allocated eth_dev
+	 * so the nulls are local per-process */
+
+	internals->nb_rx_queues = nb_rx_queues;
+	internals->nb_tx_queues = nb_tx_queues;
+	internals->packet_size = packet_size;
+	internals->packet_copy = packet_copy;
+	internals->numa_node = numa_node;
+
+	pci_dev->numa_node = numa_node;
+
+	data->dev_private = internals;
+	data->port_id = eth_dev->data->port_id;
+	data->nb_rx_queues = (uint16_t)nb_rx_queues;
+	data->nb_tx_queues = (uint16_t)nb_tx_queues;
+	data->dev_link = pmd_link;
+	data->mac_addrs = &eth_addr;
+
+	eth_dev->data = data;
+	eth_dev->dev_ops = &ops;
+	eth_dev->pci_dev = pci_dev;
+
+	/* finally assign rx and tx ops */
+	if (packet_copy) {
+		eth_dev->rx_pkt_burst = eth_null_copy_rx;
+		eth_dev->tx_pkt_burst = eth_null_copy_tx;
+	} else {
+		eth_dev->rx_pkt_burst = eth_null_rx;
+		eth_dev->tx_pkt_burst = eth_null_tx;
+	}
+
+	return 0;
+
+error:
+	if (data)
+		rte_free(data);
+	if (pci_dev)
+		rte_free(pci_dev);
+	if (internals)
+		rte_free(internals);
+	return -1;
+}
+
+static inline int
+get_packet_size_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_size = extra_args;
+
+	*packet_size = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_size == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static inline int
+get_packet_copy_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_copy = extra_args;
+
+	*packet_copy = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_copy == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static int
+rte_pmd_null_devinit(const char *name, const char *params)
+{
+	unsigned numa_node;
+	unsigned packet_size = default_packet_size;
+	unsigned packet_copy = default_packet_copy;
+	struct rte_kvargs *kvlist;
+	int ret;
+
+	RTE_LOG(INFO, PMD, "Initializing pmd_null for %s\n", name);
+
+	numa_node = rte_socket_id();
+
+	kvlist = rte_kvargs_parse(params, valid_arguments);
+	if (kvlist == NULL)
+		return -1;
+
+	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) {
+
+		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_SIZE_ARG,
+				&get_packet_size_arg, &packet_size);
+		if (ret < 0)
+			return -1;
+	}
+
+	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) {
+
+		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_COPY_ARG,
+				&get_packet_copy_arg, &packet_copy);
+		if (ret < 0)
+			return -1;
+	}
+
+	RTE_LOG(INFO, PMD, "Configure pmd_null: packet size is %d, "
+			"packet copy is %s\n", packet_size,
+			packet_copy ? "enabled" : "disabled");
+
+	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
+}
+
+static struct rte_driver pmd_null_drv = {
+	.name = "eth_null",
+	.type = PMD_VDEV,
+	.init = rte_pmd_null_devinit,
+};
+
+PMD_REGISTER_DRIVER(pmd_null_drv);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* Re: [RFC] librte_pmd_null: Add null PMD
       [not found]       ` <1411129659-7132-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2014-09-22  7:46         ` Ivan Boule
       [not found]           ` <541FD3BD.2060606-pdR9zngts4EAvxtiuMwx3w@public.gmane.org>
  0 siblings, 1 reply; 60+ messages in thread
From: Ivan Boule @ 2014-09-22  7:46 UTC (permalink / raw)
  To: mukawa-AlSX/UN32fvPDbFq/vQRIQ, dev-VfR2kkLFssw
  Cc: nakajima.yoshihiro-Zyj7fXuS5i5L9jVzuh4AOg,
	masutani.hitoshi-Zyj7fXuS5i5L9jVzuh4AOg

On 09/19/2014 02:27 PM, mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org wrote:
> From: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
>
> 'null PMD' is a virtual device driver particulary designed to measure
> performance of DPDK applications and DPDK PMDs. When an application call rx,
> null PMD just allocate mbufs and return those. Also tx, the PMD just free
> mbufs.
>
> The PMD has following options.
> - size: specify packe size allocated by RX. Default packet size is 64.
> - copy: specify 1 or 0 to enable or disable copy while RX and TX.
> 	Default value is 0(disbaled).
> 	This option is used for emulating more realistic data transfer.
> 	Copy size is equal to packet size.
Hi Tetsuya,

This is a "nice to have" PMD.

Just a minor comment.
I guess it should be NTT instead of Intel in the following comment
"#     * Neither the name of Intel Corporation nor the names of its".

Regards,
Ivan

>
> Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
> ---
>   config/common_bsdapp               |   5 +
>   config/common_linuxapp             |   5 +
>   lib/Makefile                       |   1 +
>   lib/librte_pmd_null/Makefile       |  58 +++++
>   lib/librte_pmd_null/rte_eth_null.c | 474 +++++++++++++++++++++++++++++++++++++
>   5 files changed, 543 insertions(+)
>   create mode 100644 lib/librte_pmd_null/Makefile
>   create mode 100644 lib/librte_pmd_null/rte_eth_null.c
>
> diff --git a/config/common_bsdapp b/config/common_bsdapp
> index 645949f..a86321f 100644
> --- a/config/common_bsdapp
> +++ b/config/common_bsdapp
> @@ -226,6 +226,11 @@ CONFIG_RTE_LIBRTE_PMD_PCAP=y
>   CONFIG_RTE_LIBRTE_PMD_BOND=y
>
>   #
> +# Compile null PMD
> +#
> +CONFIG_RTE_LIBRTE_PMD_NULL=y
> +
> +#
>   # Do prefetch of packet data within PMD driver receive function
>   #
>   CONFIG_RTE_PMD_PACKET_PREFETCH=y
> diff --git a/config/common_linuxapp b/config/common_linuxapp
> index 5bee910..e3bd8c0 100644
> --- a/config/common_linuxapp
> +++ b/config/common_linuxapp
> @@ -254,6 +254,11 @@ CONFIG_RTE_LIBRTE_PMD_BOND=y
>   CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
>
>   #
> +# Compile null PMD
> +#
> +CONFIG_RTE_LIBRTE_PMD_NULL=y
> +
> +#
>   # Do prefetch of packet data within PMD driver receive function
>   #
>   CONFIG_RTE_PMD_PACKET_PREFETCH=y
> diff --git a/lib/Makefile b/lib/Makefile
> index 10c5bb3..61d6ed1 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -50,6 +50,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += librte_pmd_pcap
>   DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += librte_pmd_virtio
>   DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3
>   DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt
> +DIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += librte_pmd_null
>   DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash
>   DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm
>   DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl
> diff --git a/lib/librte_pmd_null/Makefile b/lib/librte_pmd_null/Makefile
> new file mode 100644
> index 0000000..e017918
> --- /dev/null
> +++ b/lib/librte_pmd_null/Makefile
> @@ -0,0 +1,58 @@
> +#   BSD LICENSE
> +#
> +#   Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
> +#   All rights reserved.
> +#
> +#   Redistribution and use in source and binary forms, with or without
> +#   modification, are permitted provided that the following conditions
> +#   are met:
> +#
> +#     * Redistributions of source code must retain the above copyright
> +#       notice, this list of conditions and the following disclaimer.
> +#     * Redistributions in binary form must reproduce the above copyright
> +#       notice, this list of conditions and the following disclaimer in
> +#       the documentation and/or other materials provided with the
> +#       distribution.
> +#     * Neither the name of Intel Corporation nor the names of its
> +#       contributors may be used to endorse or promote products derived
> +#       from this software without specific prior written permission.
> +#
> +#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> +#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> +#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> +#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> +#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> +#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> +#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> +#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> +#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> +#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> +#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +
> +include $(RTE_SDK)/mk/rte.vars.mk
> +
> +#
> +# library name
> +#
> +LIB = librte_pmd_null.a
> +
> +CFLAGS += -O3
> +CFLAGS += $(WERROR_FLAGS)
> +
> +#
> +# all source are stored in SRCS-y
> +#
> +SRCS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += rte_eth_null.c
> +
> +#
> +# Export include files
> +#
> +SYMLINK-y-include +=
> +
> +# this lib depends upon:
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_mbuf
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_ether
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_malloc
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_kvargs
> +
> +include $(RTE_SDK)/mk/rte.lib.mk
> diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
> new file mode 100644
> index 0000000..1a81843
> --- /dev/null
> +++ b/lib/librte_pmd_null/rte_eth_null.c
> @@ -0,0 +1,474 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
> + *   All rights reserved.
> + *
> + *   Redistribution and use in source and binary forms, with or without
> + *   modification, are permitted provided that the following conditions
> + *   are met:
> + *
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in
> + *       the documentation and/or other materials provided with the
> + *       distribution.
> + *     * Neither the name of Intel Corporation nor the names of its
> + *       contributors may be used to endorse or promote products derived
> + *       from this software without specific prior written permission.
> + *
> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <rte_mbuf.h>
> +#include <rte_ethdev.h>
> +#include <rte_malloc.h>
> +#include <rte_memcpy.h>
> +#include <rte_dev.h>
> +#include <rte_kvargs.h>
> +
> +#define ETH_NULL_PACKET_SIZE_ARG	"size"
> +#define ETH_NULL_PACKET_COPY_ARG	"copy"
> +
> +static unsigned default_packet_size = 64;
> +static unsigned default_packet_copy;
> +
> +static const char const *valid_arguments[] = {
> +	ETH_NULL_PACKET_SIZE_ARG,
> +	ETH_NULL_PACKET_COPY_ARG,
> +	NULL
> +};
> +
> +struct pmd_internals;
> +
> +struct null_queue {
> +	struct pmd_internals *internals;
> +
> +	struct rte_mempool *mb_pool;
> +	struct rte_mbuf *dummy_packet;
> +
> +	rte_atomic64_t rx_pkts;
> +	rte_atomic64_t tx_pkts;
> +	rte_atomic64_t err_pkts;
> +};
> +
> +struct pmd_internals {
> +	unsigned packet_size;
> +	unsigned packet_copy;
> +	unsigned numa_node;
> +
> +	unsigned nb_rx_queues;
> +	unsigned nb_tx_queues;
> +
> +	struct null_queue rx_null_queues[1];
> +	struct null_queue tx_null_queues[1];
> +};
> +
> +
> +static struct ether_addr eth_addr = { .addr_bytes = {0} };
> +static const char *drivername = "Null PMD";
> +static struct rte_eth_link pmd_link = {
> +	.link_speed = 10000,
> +	.link_duplex = ETH_LINK_FULL_DUPLEX,
> +	.link_status = 0
> +};
> +
> +static uint16_t
> +eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
> +{
> +	int i;
> +	struct null_queue *h = q;
> +	unsigned packet_size = h->internals->packet_size;
> +
> +	for (i = 0; i < nb_bufs; i++) {
> +		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
> +		if (!bufs[i])
> +			break;
> +		bufs[i]->data_len = (uint16_t)packet_size;
> +		bufs[i]->pkt_len = packet_size;
> +		bufs[i]->nb_segs = 1;
> +		bufs[i]->next = NULL;
> +	}
> +
> +	rte_atomic64_add(&(h->rx_pkts), i);
> +
> +	return i;
> +}
> +
> +static uint16_t
> +eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
> +{
> +	int i;
> +	struct null_queue *h = q;
> +	unsigned packet_size = h->internals->packet_size;
> +
> +	for (i = 0; i < nb_bufs; i++) {
> +		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
> +		if (!bufs[i])
> +			break;
> +		rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,
> +					packet_size);
> +		bufs[i]->data_len = (uint16_t)packet_size;
> +		bufs[i]->pkt_len = packet_size;
> +		bufs[i]->nb_segs = 1;
> +		bufs[i]->next = NULL;
> +	}
> +
> +	rte_atomic64_add(&(h->rx_pkts), i);
> +
> +	return i;
> +}
> +
> +static uint16_t
> +eth_null_tx(void *q, struct rte_mbuf **bufs __rte_unused, uint16_t nb_bufs)
> +{
> +	int i;
> +	struct null_queue *h = q;
> +
> +	for (i = 0; i < nb_bufs; i++)
> +		rte_pktmbuf_free(bufs[i]);
> +
> +	rte_atomic64_add(&(h->tx_pkts), i);
> +
> +	return i;
> +}
> +
> +static uint16_t
> +eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
> +{
> +	int i;
> +	struct null_queue *h = q;
> +	unsigned packet_size = h->internals->packet_size;
> +
> +	for (i = 0; i < nb_bufs; i++) {
> +		rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *),
> +					packet_size);
> +		rte_pktmbuf_free(bufs[i]);
> +	}
> +
> +	rte_atomic64_add(&(h->tx_pkts), i);
> +
> +	return i;
> +}
> +
> +static int
> +eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; }
> +
> +static int
> +eth_dev_start(struct rte_eth_dev *dev)
> +{
> +	dev->data->dev_link.link_status = 1;
> +	return 0;
> +}
> +
> +static void
> +eth_dev_stop(struct rte_eth_dev *dev)
> +{
> +	dev->data->dev_link.link_status = 0;
> +}
> +
> +static int
> +eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
> +		uint16_t nb_rx_desc __rte_unused,
> +		unsigned int socket_id __rte_unused,
> +		const struct rte_eth_rxconf *rx_conf __rte_unused,
> +		struct rte_mempool *mb_pool __rte_unused)
> +{
> +	struct rte_mbuf *dummy_packet;
> +	struct pmd_internals *internals = dev->data->dev_private;
> +	unsigned packet_size = internals->packet_size;
> +
> +	if (rx_queue_id != 0)
> +			return -ENODEV;
> +
> +	internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool;
> +	dev->data->rx_queues[rx_queue_id] =
> +		&internals->rx_null_queues[rx_queue_id];
> +	dummy_packet = rte_zmalloc_socket(NULL,
> +			packet_size, 0, internals->numa_node);
> +	if (dummy_packet == NULL)
> +		return -ENOMEM;
> +
> +	internals->rx_null_queues[rx_queue_id].internals = internals;
> +	internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet;
> +
> +	return 0;
> +}
> +
> +static int
> +eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
> +		uint16_t nb_tx_desc __rte_unused,
> +		unsigned int socket_id __rte_unused,
> +		const struct rte_eth_txconf *tx_conf __rte_unused)
> +{
> +	struct rte_mbuf *dummy_packet;
> +	struct pmd_internals *internals = dev->data->dev_private;
> +	unsigned packet_size = internals->packet_size;
> +
> +	if (tx_queue_id != 0)
> +			return -ENODEV;
> +
> +	dev->data->tx_queues[tx_queue_id] =
> +		&internals->tx_null_queues[tx_queue_id];
> +	dummy_packet = rte_zmalloc_socket(NULL,
> +			packet_size, 0, internals->numa_node);
> +	if (dummy_packet == NULL)
> +		return -ENOMEM;
> +
> +	internals->tx_null_queues[tx_queue_id].internals = internals;
> +	internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet;
> +
> +	return 0;
> +}
> +
> +
> +static void
> +eth_dev_info(struct rte_eth_dev *dev,
> +		struct rte_eth_dev_info *dev_info)
> +{
> +	struct pmd_internals *internals = dev->data->dev_private;
> +
> +	dev_info->driver_name = drivername;
> +	dev_info->max_mac_addrs = 1;
> +	dev_info->max_rx_pktlen = (uint32_t)-1;
> +	dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;
> +	dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;
> +	dev_info->min_rx_bufsize = 0;
> +	dev_info->pci_dev = NULL;
> +}
> +
> +static void
> +eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)
> +{
> +	unsigned i;
> +	unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
> +	const struct pmd_internals *internal = dev->data->dev_private;
> +
> +	memset(igb_stats, 0, sizeof(*igb_stats));
> +	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
> +			i < internal->nb_rx_queues; i++) {
> +		igb_stats->q_ipackets[i] =
> +			internal->rx_null_queues[i].rx_pkts.cnt;
> +		rx_total += igb_stats->q_ipackets[i];
> +	}
> +
> +	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
> +			i < internal->nb_tx_queues; i++) {
> +		igb_stats->q_opackets[i] =
> +			internal->tx_null_queues[i].tx_pkts.cnt;
> +		igb_stats->q_errors[i] =
> +			internal->tx_null_queues[i].err_pkts.cnt;
> +		tx_total += igb_stats->q_opackets[i];
> +		tx_err_total += igb_stats->q_errors[i];
> +	}
> +
> +	igb_stats->ipackets = rx_total;
> +	igb_stats->opackets = tx_total;
> +	igb_stats->oerrors = tx_err_total;
> +}
> +
> +static void
> +eth_stats_reset(struct rte_eth_dev *dev)
> +{
> +	unsigned i;
> +	struct pmd_internals *internal = dev->data->dev_private;
> +
> +	for (i = 0; i < internal->nb_rx_queues; i++)
> +		internal->rx_null_queues[i].rx_pkts.cnt = 0;
> +	for (i = 0; i < internal->nb_tx_queues; i++) {
> +		internal->tx_null_queues[i].tx_pkts.cnt = 0;
> +		internal->tx_null_queues[i].err_pkts.cnt = 0;
> +	}
> +}
> +
> +static void
> +eth_queue_release(void *q __rte_unused) { ; }
> +static int
> +eth_link_update(struct rte_eth_dev *dev __rte_unused,
> +		int wait_to_complete __rte_unused) { return 0; }
> +
> +static struct eth_dev_ops ops = {
> +		.dev_start = eth_dev_start,
> +		.dev_stop = eth_dev_stop,
> +		.dev_configure = eth_dev_configure,
> +		.dev_infos_get = eth_dev_info,
> +		.rx_queue_setup = eth_rx_queue_setup,
> +		.tx_queue_setup = eth_tx_queue_setup,
> +		.rx_queue_release = eth_queue_release,
> +		.tx_queue_release = eth_queue_release,
> +		.link_update = eth_link_update,
> +		.stats_get = eth_stats_get,
> +		.stats_reset = eth_stats_reset,
> +};
> +
> +static int
> +eth_dev_null_create(const char *name __rte_unused,
> +		const unsigned numa_node,
> +		unsigned packet_size,
> +		unsigned packet_copy)
> +{
> +	const unsigned nb_rx_queues = 1;
> +	const unsigned nb_tx_queues = 1;
> +	struct rte_eth_dev_data *data = NULL;
> +	struct rte_pci_device *pci_dev = NULL;
> +	struct pmd_internals *internals = NULL;
> +	struct rte_eth_dev *eth_dev = NULL;
> +
> +	RTE_LOG(INFO, PMD, "Creating null ethdev on numa socket %u\n",
> +			numa_node);
> +
> +	/* now do all data allocation - for eth_dev structure, dummy pci driver
> +	 * and internal (private) data
> +	 */
> +	data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);
> +	if (data == NULL)
> +		goto error;
> +
> +	pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);
> +	if (pci_dev == NULL)
> +		goto error;
> +
> +	internals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node);
> +	if (internals == NULL)
> +		goto error;
> +
> +	/* reserve an ethdev entry */
> +	eth_dev = rte_eth_dev_allocate(name);
> +	if (eth_dev == NULL)
> +		goto error;
> +
> +	/* now put it all together
> +	 * - store queue data in internals,
> +	 * - store numa_node info in pci_driver
> +	 * - point eth_dev_data to internals and pci_driver
> +	 * - and point eth_dev structure to new eth_dev_data structure
> +	 */
> +	/* NOTE: we'll replace the data element, of originally allocated eth_dev
> +	 * so the nulls are local per-process */
> +
> +	internals->nb_rx_queues = nb_rx_queues;
> +	internals->nb_tx_queues = nb_tx_queues;
> +	internals->packet_size = packet_size;
> +	internals->packet_copy = packet_copy;
> +	internals->numa_node = numa_node;
> +
> +	pci_dev->numa_node = numa_node;
> +
> +	data->dev_private = internals;
> +	data->port_id = eth_dev->data->port_id;
> +	data->nb_rx_queues = (uint16_t)nb_rx_queues;
> +	data->nb_tx_queues = (uint16_t)nb_tx_queues;
> +	data->dev_link = pmd_link;
> +	data->mac_addrs = &eth_addr;
> +
> +	eth_dev->data = data;
> +	eth_dev->dev_ops = &ops;
> +	eth_dev->pci_dev = pci_dev;
> +
> +	/* finally assign rx and tx ops */
> +	if (packet_copy) {
> +		eth_dev->rx_pkt_burst = eth_null_copy_rx;
> +		eth_dev->tx_pkt_burst = eth_null_copy_tx;
> +	} else {
> +		eth_dev->rx_pkt_burst = eth_null_rx;
> +		eth_dev->tx_pkt_burst = eth_null_tx;
> +	}
> +
> +	return 0;
> +
> +error:
> +	if (data)
> +		rte_free(data);
> +	if (pci_dev)
> +		rte_free(pci_dev);
> +	if (internals)
> +		rte_free(internals);
> +	return -1;
> +}
> +
> +static inline int
> +get_packet_size_arg(const char *key __rte_unused,
> +		const char *value, void *extra_args)
> +{
> +	const char *a = value;
> +	unsigned *packet_size = extra_args;
> +
> +	*packet_size = (unsigned)strtoul(a, NULL, 0);
> +	if (*packet_size == UINT_MAX)
> +		return -1;
> +
> +	return 0;
> +}
> +
> +static inline int
> +get_packet_copy_arg(const char *key __rte_unused,
> +		const char *value, void *extra_args)
> +{
> +	const char *a = value;
> +	unsigned *packet_copy = extra_args;
> +
> +	*packet_copy = (unsigned)strtoul(a, NULL, 0);
> +	if (*packet_copy == UINT_MAX)
> +		return -1;
> +
> +	return 0;
> +}
> +
> +static int
> +rte_pmd_null_devinit(const char *name, const char *params)
> +{
> +	unsigned numa_node;
> +	unsigned packet_size = default_packet_size;
> +	unsigned packet_copy = default_packet_copy;
> +	struct rte_kvargs *kvlist;
> +	int ret;
> +
> +	RTE_LOG(INFO, PMD, "Initializing pmd_null for %s\n", name);
> +
> +	numa_node = rte_socket_id();
> +
> +	kvlist = rte_kvargs_parse(params, valid_arguments);
> +	if (kvlist == NULL)
> +		return -1;
> +
> +	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) {
> +
> +		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_SIZE_ARG,
> +				&get_packet_size_arg, &packet_size);
> +		if (ret < 0)
> +			return -1;
> +	}
> +
> +	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) {
> +
> +		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_COPY_ARG,
> +				&get_packet_copy_arg, &packet_copy);
> +		if (ret < 0)
> +			return -1;
> +	}
> +
> +	RTE_LOG(INFO, PMD, "Configure pmd_null: packet size is %d, "
> +			"packet copy is %s\n", packet_size,
> +			packet_copy ? "enabled" : "disabled");
> +
> +	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
> +}
> +
> +static struct rte_driver pmd_null_drv = {
> +	.name = "eth_null",
> +	.type = PMD_VDEV,
> +	.init = rte_pmd_null_devinit,
> +};
> +
> +PMD_REGISTER_DRIVER(pmd_null_drv);
>


-- 
Ivan Boule
6WIND Development Engineer

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [RFC] librte_pmd_null: Add null PMD
       [not found]           ` <541FD3BD.2060606-pdR9zngts4EAvxtiuMwx3w@public.gmane.org>
@ 2014-09-22  8:07             ` Tetsuya Mukawa
  0 siblings, 0 replies; 60+ messages in thread
From: Tetsuya Mukawa @ 2014-09-22  8:07 UTC (permalink / raw)
  To: Ivan Boule, dev-VfR2kkLFssw
  Cc: nakajima.yoshihiro-Zyj7fXuS5i5L9jVzuh4AOg,
	masutani.hitoshi-Zyj7fXuS5i5L9jVzuh4AOg

Hi Ivan

(2014/09/22 16:46), Ivan Boule wrote:
>
> This is a "nice to have" PMD.
>
> Just a minor comment.
> I guess it should be NTT instead of Intel in the following comment
> "#     * Neither the name of Intel Corporation nor the names of its".
>
I appreciate your comment. I will rewrite and post it again.

Regards,
Tetsuya


> Regards,
> Ivan
>
>>
>> Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
>> ---
>>   config/common_bsdapp               |   5 +
>>   config/common_linuxapp             |   5 +
>>   lib/Makefile                       |   1 +
>>   lib/librte_pmd_null/Makefile       |  58 +++++
>>   lib/librte_pmd_null/rte_eth_null.c | 474
>> +++++++++++++++++++++++++++++++++++++
>>   5 files changed, 543 insertions(+)
>>   create mode 100644 lib/librte_pmd_null/Makefile
>>   create mode 100644 lib/librte_pmd_null/rte_eth_null.c
>>
>> diff --git a/config/common_bsdapp b/config/common_bsdapp
>> index 645949f..a86321f 100644
>> --- a/config/common_bsdapp
>> +++ b/config/common_bsdapp
>> @@ -226,6 +226,11 @@ CONFIG_RTE_LIBRTE_PMD_PCAP=y
>>   CONFIG_RTE_LIBRTE_PMD_BOND=y
>>
>>   #
>> +# Compile null PMD
>> +#
>> +CONFIG_RTE_LIBRTE_PMD_NULL=y
>> +
>> +#
>>   # Do prefetch of packet data within PMD driver receive function
>>   #
>>   CONFIG_RTE_PMD_PACKET_PREFETCH=y
>> diff --git a/config/common_linuxapp b/config/common_linuxapp
>> index 5bee910..e3bd8c0 100644
>> --- a/config/common_linuxapp
>> +++ b/config/common_linuxapp
>> @@ -254,6 +254,11 @@ CONFIG_RTE_LIBRTE_PMD_BOND=y
>>   CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
>>
>>   #
>> +# Compile null PMD
>> +#
>> +CONFIG_RTE_LIBRTE_PMD_NULL=y
>> +
>> +#
>>   # Do prefetch of packet data within PMD driver receive function
>>   #
>>   CONFIG_RTE_PMD_PACKET_PREFETCH=y
>> diff --git a/lib/Makefile b/lib/Makefile
>> index 10c5bb3..61d6ed1 100644
>> --- a/lib/Makefile
>> +++ b/lib/Makefile
>> @@ -50,6 +50,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += librte_pmd_pcap
>>   DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += librte_pmd_virtio
>>   DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3
>>   DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt
>> +DIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += librte_pmd_null
>>   DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash
>>   DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm
>>   DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl
>> diff --git a/lib/librte_pmd_null/Makefile b/lib/librte_pmd_null/Makefile
>> new file mode 100644
>> index 0000000..e017918
>> --- /dev/null
>> +++ b/lib/librte_pmd_null/Makefile
>> @@ -0,0 +1,58 @@
>> +#   BSD LICENSE
>> +#
>> +#   Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
>> +#   All rights reserved.
>> +#
>> +#   Redistribution and use in source and binary forms, with or without
>> +#   modification, are permitted provided that the following conditions
>> +#   are met:
>> +#
>> +#     * Redistributions of source code must retain the above copyright
>> +#       notice, this list of conditions and the following disclaimer.
>> +#     * Redistributions in binary form must reproduce the above
>> copyright
>> +#       notice, this list of conditions and the following disclaimer in
>> +#       the documentation and/or other materials provided with the
>> +#       distribution.
>> +#     * Neither the name of Intel Corporation nor the names of its
>> +#       contributors may be used to endorse or promote products derived
>> +#       from this software without specific prior written permission.
>> +#
>> +#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
>> +#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
>> +#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
>> FITNESS FOR
>> +#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
>> COPYRIGHT
>> +#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
>> INCIDENTAL,
>> +#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
>> +#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
>> USE,
>> +#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
>> ON ANY
>> +#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
>> +#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
>> THE USE
>> +#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
>> DAMAGE.
>> +
>> +include $(RTE_SDK)/mk/rte.vars.mk
>> +
>> +#
>> +# library name
>> +#
>> +LIB = librte_pmd_null.a
>> +
>> +CFLAGS += -O3
>> +CFLAGS += $(WERROR_FLAGS)
>> +
>> +#
>> +# all source are stored in SRCS-y
>> +#
>> +SRCS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += rte_eth_null.c
>> +
>> +#
>> +# Export include files
>> +#
>> +SYMLINK-y-include +=
>> +
>> +# this lib depends upon:
>> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_mbuf
>> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_ether
>> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_malloc
>> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_kvargs
>> +
>> +include $(RTE_SDK)/mk/rte.lib.mk
>> diff --git a/lib/librte_pmd_null/rte_eth_null.c
>> b/lib/librte_pmd_null/rte_eth_null.c
>> new file mode 100644
>> index 0000000..1a81843
>> --- /dev/null
>> +++ b/lib/librte_pmd_null/rte_eth_null.c
>> @@ -0,0 +1,474 @@
>> +/*-
>> + *   BSD LICENSE
>> + *
>> + *   Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
>> + *   All rights reserved.
>> + *
>> + *   Redistribution and use in source and binary forms, with or without
>> + *   modification, are permitted provided that the following conditions
>> + *   are met:
>> + *
>> + *     * Redistributions of source code must retain the above copyright
>> + *       notice, this list of conditions and the following disclaimer.
>> + *     * Redistributions in binary form must reproduce the above
>> copyright
>> + *       notice, this list of conditions and the following
>> disclaimer in
>> + *       the documentation and/or other materials provided with the
>> + *       distribution.
>> + *     * Neither the name of Intel Corporation nor the names of its
>> + *       contributors may be used to endorse or promote products
>> derived
>> + *       from this software without specific prior written permission.
>> + *
>> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
>> CONTRIBUTORS
>> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
>> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
>> FITNESS FOR
>> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
>> COPYRIGHT
>> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
>> INCIDENTAL,
>> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
>> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
>> OF USE,
>> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
>> ON ANY
>> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
>> TORT
>> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
>> THE USE
>> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
>> DAMAGE.
>> + */
>> +
>> +#include <rte_mbuf.h>
>> +#include <rte_ethdev.h>
>> +#include <rte_malloc.h>
>> +#include <rte_memcpy.h>
>> +#include <rte_dev.h>
>> +#include <rte_kvargs.h>
>> +
>> +#define ETH_NULL_PACKET_SIZE_ARG    "size"
>> +#define ETH_NULL_PACKET_COPY_ARG    "copy"
>> +
>> +static unsigned default_packet_size = 64;
>> +static unsigned default_packet_copy;
>> +
>> +static const char const *valid_arguments[] = {
>> +    ETH_NULL_PACKET_SIZE_ARG,
>> +    ETH_NULL_PACKET_COPY_ARG,
>> +    NULL
>> +};
>> +
>> +struct pmd_internals;
>> +
>> +struct null_queue {
>> +    struct pmd_internals *internals;
>> +
>> +    struct rte_mempool *mb_pool;
>> +    struct rte_mbuf *dummy_packet;
>> +
>> +    rte_atomic64_t rx_pkts;
>> +    rte_atomic64_t tx_pkts;
>> +    rte_atomic64_t err_pkts;
>> +};
>> +
>> +struct pmd_internals {
>> +    unsigned packet_size;
>> +    unsigned packet_copy;
>> +    unsigned numa_node;
>> +
>> +    unsigned nb_rx_queues;
>> +    unsigned nb_tx_queues;
>> +
>> +    struct null_queue rx_null_queues[1];
>> +    struct null_queue tx_null_queues[1];
>> +};
>> +
>> +
>> +static struct ether_addr eth_addr = { .addr_bytes = {0} };
>> +static const char *drivername = "Null PMD";
>> +static struct rte_eth_link pmd_link = {
>> +    .link_speed = 10000,
>> +    .link_duplex = ETH_LINK_FULL_DUPLEX,
>> +    .link_status = 0
>> +};
>> +
>> +static uint16_t
>> +eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
>> +{
>> +    int i;
>> +    struct null_queue *h = q;
>> +    unsigned packet_size = h->internals->packet_size;
>> +
>> +    for (i = 0; i < nb_bufs; i++) {
>> +        bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
>> +        if (!bufs[i])
>> +            break;
>> +        bufs[i]->data_len = (uint16_t)packet_size;
>> +        bufs[i]->pkt_len = packet_size;
>> +        bufs[i]->nb_segs = 1;
>> +        bufs[i]->next = NULL;
>> +    }
>> +
>> +    rte_atomic64_add(&(h->rx_pkts), i);
>> +
>> +    return i;
>> +}
>> +
>> +static uint16_t
>> +eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
>> +{
>> +    int i;
>> +    struct null_queue *h = q;
>> +    unsigned packet_size = h->internals->packet_size;
>> +
>> +    for (i = 0; i < nb_bufs; i++) {
>> +        bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
>> +        if (!bufs[i])
>> +            break;
>> +        rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,
>> +                    packet_size);
>> +        bufs[i]->data_len = (uint16_t)packet_size;
>> +        bufs[i]->pkt_len = packet_size;
>> +        bufs[i]->nb_segs = 1;
>> +        bufs[i]->next = NULL;
>> +    }
>> +
>> +    rte_atomic64_add(&(h->rx_pkts), i);
>> +
>> +    return i;
>> +}
>> +
>> +static uint16_t
>> +eth_null_tx(void *q, struct rte_mbuf **bufs __rte_unused, uint16_t
>> nb_bufs)
>> +{
>> +    int i;
>> +    struct null_queue *h = q;
>> +
>> +    for (i = 0; i < nb_bufs; i++)
>> +        rte_pktmbuf_free(bufs[i]);
>> +
>> +    rte_atomic64_add(&(h->tx_pkts), i);
>> +
>> +    return i;
>> +}
>> +
>> +static uint16_t
>> +eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
>> +{
>> +    int i;
>> +    struct null_queue *h = q;
>> +    unsigned packet_size = h->internals->packet_size;
>> +
>> +    for (i = 0; i < nb_bufs; i++) {
>> +        rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *),
>> +                    packet_size);
>> +        rte_pktmbuf_free(bufs[i]);
>> +    }
>> +
>> +    rte_atomic64_add(&(h->tx_pkts), i);
>> +
>> +    return i;
>> +}
>> +
>> +static int
>> +eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; }
>> +
>> +static int
>> +eth_dev_start(struct rte_eth_dev *dev)
>> +{
>> +    dev->data->dev_link.link_status = 1;
>> +    return 0;
>> +}
>> +
>> +static void
>> +eth_dev_stop(struct rte_eth_dev *dev)
>> +{
>> +    dev->data->dev_link.link_status = 0;
>> +}
>> +
>> +static int
>> +eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
>> +        uint16_t nb_rx_desc __rte_unused,
>> +        unsigned int socket_id __rte_unused,
>> +        const struct rte_eth_rxconf *rx_conf __rte_unused,
>> +        struct rte_mempool *mb_pool __rte_unused)
>> +{
>> +    struct rte_mbuf *dummy_packet;
>> +    struct pmd_internals *internals = dev->data->dev_private;
>> +    unsigned packet_size = internals->packet_size;
>> +
>> +    if (rx_queue_id != 0)
>> +            return -ENODEV;
>> +
>> +    internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool;
>> +    dev->data->rx_queues[rx_queue_id] =
>> +        &internals->rx_null_queues[rx_queue_id];
>> +    dummy_packet = rte_zmalloc_socket(NULL,
>> +            packet_size, 0, internals->numa_node);
>> +    if (dummy_packet == NULL)
>> +        return -ENOMEM;
>> +
>> +    internals->rx_null_queues[rx_queue_id].internals = internals;
>> +    internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet;
>> +
>> +    return 0;
>> +}
>> +
>> +static int
>> +eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
>> +        uint16_t nb_tx_desc __rte_unused,
>> +        unsigned int socket_id __rte_unused,
>> +        const struct rte_eth_txconf *tx_conf __rte_unused)
>> +{
>> +    struct rte_mbuf *dummy_packet;
>> +    struct pmd_internals *internals = dev->data->dev_private;
>> +    unsigned packet_size = internals->packet_size;
>> +
>> +    if (tx_queue_id != 0)
>> +            return -ENODEV;
>> +
>> +    dev->data->tx_queues[tx_queue_id] =
>> +        &internals->tx_null_queues[tx_queue_id];
>> +    dummy_packet = rte_zmalloc_socket(NULL,
>> +            packet_size, 0, internals->numa_node);
>> +    if (dummy_packet == NULL)
>> +        return -ENOMEM;
>> +
>> +    internals->tx_null_queues[tx_queue_id].internals = internals;
>> +    internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet;
>> +
>> +    return 0;
>> +}
>> +
>> +
>> +static void
>> +eth_dev_info(struct rte_eth_dev *dev,
>> +        struct rte_eth_dev_info *dev_info)
>> +{
>> +    struct pmd_internals *internals = dev->data->dev_private;
>> +
>> +    dev_info->driver_name = drivername;
>> +    dev_info->max_mac_addrs = 1;
>> +    dev_info->max_rx_pktlen = (uint32_t)-1;
>> +    dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;
>> +    dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;
>> +    dev_info->min_rx_bufsize = 0;
>> +    dev_info->pci_dev = NULL;
>> +}
>> +
>> +static void
>> +eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)
>> +{
>> +    unsigned i;
>> +    unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
>> +    const struct pmd_internals *internal = dev->data->dev_private;
>> +
>> +    memset(igb_stats, 0, sizeof(*igb_stats));
>> +    for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
>> +            i < internal->nb_rx_queues; i++) {
>> +        igb_stats->q_ipackets[i] =
>> +            internal->rx_null_queues[i].rx_pkts.cnt;
>> +        rx_total += igb_stats->q_ipackets[i];
>> +    }
>> +
>> +    for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
>> +            i < internal->nb_tx_queues; i++) {
>> +        igb_stats->q_opackets[i] =
>> +            internal->tx_null_queues[i].tx_pkts.cnt;
>> +        igb_stats->q_errors[i] =
>> +            internal->tx_null_queues[i].err_pkts.cnt;
>> +        tx_total += igb_stats->q_opackets[i];
>> +        tx_err_total += igb_stats->q_errors[i];
>> +    }
>> +
>> +    igb_stats->ipackets = rx_total;
>> +    igb_stats->opackets = tx_total;
>> +    igb_stats->oerrors = tx_err_total;
>> +}
>> +
>> +static void
>> +eth_stats_reset(struct rte_eth_dev *dev)
>> +{
>> +    unsigned i;
>> +    struct pmd_internals *internal = dev->data->dev_private;
>> +
>> +    for (i = 0; i < internal->nb_rx_queues; i++)
>> +        internal->rx_null_queues[i].rx_pkts.cnt = 0;
>> +    for (i = 0; i < internal->nb_tx_queues; i++) {
>> +        internal->tx_null_queues[i].tx_pkts.cnt = 0;
>> +        internal->tx_null_queues[i].err_pkts.cnt = 0;
>> +    }
>> +}
>> +
>> +static void
>> +eth_queue_release(void *q __rte_unused) { ; }
>> +static int
>> +eth_link_update(struct rte_eth_dev *dev __rte_unused,
>> +        int wait_to_complete __rte_unused) { return 0; }
>> +
>> +static struct eth_dev_ops ops = {
>> +        .dev_start = eth_dev_start,
>> +        .dev_stop = eth_dev_stop,
>> +        .dev_configure = eth_dev_configure,
>> +        .dev_infos_get = eth_dev_info,
>> +        .rx_queue_setup = eth_rx_queue_setup,
>> +        .tx_queue_setup = eth_tx_queue_setup,
>> +        .rx_queue_release = eth_queue_release,
>> +        .tx_queue_release = eth_queue_release,
>> +        .link_update = eth_link_update,
>> +        .stats_get = eth_stats_get,
>> +        .stats_reset = eth_stats_reset,
>> +};
>> +
>> +static int
>> +eth_dev_null_create(const char *name __rte_unused,
>> +        const unsigned numa_node,
>> +        unsigned packet_size,
>> +        unsigned packet_copy)
>> +{
>> +    const unsigned nb_rx_queues = 1;
>> +    const unsigned nb_tx_queues = 1;
>> +    struct rte_eth_dev_data *data = NULL;
>> +    struct rte_pci_device *pci_dev = NULL;
>> +    struct pmd_internals *internals = NULL;
>> +    struct rte_eth_dev *eth_dev = NULL;
>> +
>> +    RTE_LOG(INFO, PMD, "Creating null ethdev on numa socket %u\n",
>> +            numa_node);
>> +
>> +    /* now do all data allocation - for eth_dev structure, dummy pci
>> driver
>> +     * and internal (private) data
>> +     */
>> +    data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);
>> +    if (data == NULL)
>> +        goto error;
>> +
>> +    pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);
>> +    if (pci_dev == NULL)
>> +        goto error;
>> +
>> +    internals = rte_zmalloc_socket(name, sizeof(*internals), 0,
>> numa_node);
>> +    if (internals == NULL)
>> +        goto error;
>> +
>> +    /* reserve an ethdev entry */
>> +    eth_dev = rte_eth_dev_allocate(name);
>> +    if (eth_dev == NULL)
>> +        goto error;
>> +
>> +    /* now put it all together
>> +     * - store queue data in internals,
>> +     * - store numa_node info in pci_driver
>> +     * - point eth_dev_data to internals and pci_driver
>> +     * - and point eth_dev structure to new eth_dev_data structure
>> +     */
>> +    /* NOTE: we'll replace the data element, of originally allocated
>> eth_dev
>> +     * so the nulls are local per-process */
>> +
>> +    internals->nb_rx_queues = nb_rx_queues;
>> +    internals->nb_tx_queues = nb_tx_queues;
>> +    internals->packet_size = packet_size;
>> +    internals->packet_copy = packet_copy;
>> +    internals->numa_node = numa_node;
>> +
>> +    pci_dev->numa_node = numa_node;
>> +
>> +    data->dev_private = internals;
>> +    data->port_id = eth_dev->data->port_id;
>> +    data->nb_rx_queues = (uint16_t)nb_rx_queues;
>> +    data->nb_tx_queues = (uint16_t)nb_tx_queues;
>> +    data->dev_link = pmd_link;
>> +    data->mac_addrs = &eth_addr;
>> +
>> +    eth_dev->data = data;
>> +    eth_dev->dev_ops = &ops;
>> +    eth_dev->pci_dev = pci_dev;
>> +
>> +    /* finally assign rx and tx ops */
>> +    if (packet_copy) {
>> +        eth_dev->rx_pkt_burst = eth_null_copy_rx;
>> +        eth_dev->tx_pkt_burst = eth_null_copy_tx;
>> +    } else {
>> +        eth_dev->rx_pkt_burst = eth_null_rx;
>> +        eth_dev->tx_pkt_burst = eth_null_tx;
>> +    }
>> +
>> +    return 0;
>> +
>> +error:
>> +    if (data)
>> +        rte_free(data);
>> +    if (pci_dev)
>> +        rte_free(pci_dev);
>> +    if (internals)
>> +        rte_free(internals);
>> +    return -1;
>> +}
>> +
>> +static inline int
>> +get_packet_size_arg(const char *key __rte_unused,
>> +        const char *value, void *extra_args)
>> +{
>> +    const char *a = value;
>> +    unsigned *packet_size = extra_args;
>> +
>> +    *packet_size = (unsigned)strtoul(a, NULL, 0);
>> +    if (*packet_size == UINT_MAX)
>> +        return -1;
>> +
>> +    return 0;
>> +}
>> +
>> +static inline int
>> +get_packet_copy_arg(const char *key __rte_unused,
>> +        const char *value, void *extra_args)
>> +{
>> +    const char *a = value;
>> +    unsigned *packet_copy = extra_args;
>> +
>> +    *packet_copy = (unsigned)strtoul(a, NULL, 0);
>> +    if (*packet_copy == UINT_MAX)
>> +        return -1;
>> +
>> +    return 0;
>> +}
>> +
>> +static int
>> +rte_pmd_null_devinit(const char *name, const char *params)
>> +{
>> +    unsigned numa_node;
>> +    unsigned packet_size = default_packet_size;
>> +    unsigned packet_copy = default_packet_copy;
>> +    struct rte_kvargs *kvlist;
>> +    int ret;
>> +
>> +    RTE_LOG(INFO, PMD, "Initializing pmd_null for %s\n", name);
>> +
>> +    numa_node = rte_socket_id();
>> +
>> +    kvlist = rte_kvargs_parse(params, valid_arguments);
>> +    if (kvlist == NULL)
>> +        return -1;
>> +
>> +    if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) {
>> +
>> +        ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_SIZE_ARG,
>> +                &get_packet_size_arg, &packet_size);
>> +        if (ret < 0)
>> +            return -1;
>> +    }
>> +
>> +    if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) {
>> +
>> +        ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_COPY_ARG,
>> +                &get_packet_copy_arg, &packet_copy);
>> +        if (ret < 0)
>> +            return -1;
>> +    }
>> +
>> +    RTE_LOG(INFO, PMD, "Configure pmd_null: packet size is %d, "
>> +            "packet copy is %s\n", packet_size,
>> +            packet_copy ? "enabled" : "disabled");
>> +
>> +    return eth_dev_null_create(name, numa_node, packet_size,
>> packet_copy);
>> +}
>> +
>> +static struct rte_driver pmd_null_drv = {
>> +    .name = "eth_null",
>> +    .type = PMD_VDEV,
>> +    .init = rte_pmd_null_devinit,
>> +};
>> +
>> +PMD_REGISTER_DRIVER(pmd_null_drv);
>>
>
>

^ permalink raw reply	[flat|nested] 60+ messages in thread

* [PATCH 0/2] PMD for performance measurement
       [not found] <mukawa@igel.co.jp>
  2014-09-19 12:27 ` [RFC] PMD for performance measurement mukawa-AlSX/UN32fvPDbFq/vQRIQ
@ 2014-09-30  9:56 ` mukawa-AlSX/UN32fvPDbFq/vQRIQ
       [not found]   ` <1412070970-5625-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  2014-10-01  4:27 ` [PATCH] Fix linking errors when CONFIG_RTE_BUILD_SHARED_LIB is enabled mukawa-AlSX/UN32fvPDbFq/vQRIQ
  2014-10-01  4:57 ` [PATCH v2] PMD for performance measurement mukawa-AlSX/UN32fvPDbFq/vQRIQ
  3 siblings, 1 reply; 60+ messages in thread
From: mukawa-AlSX/UN32fvPDbFq/vQRIQ @ 2014-09-30  9:56 UTC (permalink / raw)
  To: dev-VfR2kkLFssw
  Cc: nakajima.yoshihiro-Zyj7fXuS5i5L9jVzuh4AOg,
	masutani.hitoshi-Zyj7fXuS5i5L9jVzuh4AOg

From: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>

Hi,

Here are patches to add the new PMD like '/dev/null'.
This PMD is a driver for virtual device. When an application call rx,
it just allocates mbufs and returns those. Also tx, it just frees mbufs.

Main purpose of the PMD is measuring rough throughputs of a VDEV PMD.
To measure rough throughputs between PMD1 and PMD2, prepare following
environment.

+-------------------------------+
|           testpmd1            |
+-------------+------+----------+
| Target PMD1 |      | null PMD |
+---++--------+      +----------+
    ||
    || Target path
    ||
+---++--------+      +----------+
| Target PMD2 |      | null PMD |
+-------------+------+----------+
|           testpmd2            |
+-------------------------------+

changes from RFC:
* change the copyright of this PMD.
* change commit logs.

Tetsuya Mukawa (2):
  librte_pmd_null: Add null PMD
  librte_pmd_null: Enable librte_pmd_null

 config/common_bsdapp               |   5 +
 config/common_linuxapp             |   5 +
 lib/Makefile                       |   1 +
 lib/librte_pmd_null/Makefile       |  58 +++++
 lib/librte_pmd_null/rte_eth_null.c | 474 +++++++++++++++++++++++++++++++++++++
 mk/rte.app.mk                      |   4 +
 6 files changed, 547 insertions(+)
 create mode 100644 lib/librte_pmd_null/Makefile
 create mode 100644 lib/librte_pmd_null/rte_eth_null.c

-- 
1.9.1

^ permalink raw reply	[flat|nested] 60+ messages in thread

* [PATCH 1/2] librte_pmd_null: Add null PMD
       [not found]   ` <1412070970-5625-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2014-09-30  9:56     ` mukawa-AlSX/UN32fvPDbFq/vQRIQ
       [not found]       ` <1412070970-5625-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  2014-09-30  9:56     ` [PATCH 2/2] librte_pmd_null: Enable librte_pmd_null mukawa-AlSX/UN32fvPDbFq/vQRIQ
  1 sibling, 1 reply; 60+ messages in thread
From: mukawa-AlSX/UN32fvPDbFq/vQRIQ @ 2014-09-30  9:56 UTC (permalink / raw)
  To: dev-VfR2kkLFssw
  Cc: nakajima.yoshihiro-Zyj7fXuS5i5L9jVzuh4AOg,
	masutani.hitoshi-Zyj7fXuS5i5L9jVzuh4AOg

From: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>

'null PMD' is a driver of the virtual device particulary designed to measure
performance of DPDK PMDs. When an application call rx, null PMD just allocates
mbufs and returns those. Also tx, the PMD just frees mbufs.

The PMD has following options.
- size: specify packe size allocated by RX. Default packet size is 64.
- copy: specify 1 or 0 to enable or disable copy while RX and TX.
	Default value is 0(disbaled).
	This option is used for emulating more realistic data transfer.
	Copy size is equal to packet size.

Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
---
 config/common_bsdapp               |   5 +
 config/common_linuxapp             |   5 +
 lib/Makefile                       |   1 +
 lib/librte_pmd_null/Makefile       |  58 +++++
 lib/librte_pmd_null/rte_eth_null.c | 474 +++++++++++++++++++++++++++++++++++++
 5 files changed, 543 insertions(+)
 create mode 100644 lib/librte_pmd_null/Makefile
 create mode 100644 lib/librte_pmd_null/rte_eth_null.c

diff --git a/config/common_bsdapp b/config/common_bsdapp
index eebd05b..bda37f5 100644
--- a/config/common_bsdapp
+++ b/config/common_bsdapp
@@ -224,6 +224,11 @@ CONFIG_RTE_LIBRTE_PMD_PCAP=y
 CONFIG_RTE_LIBRTE_PMD_BOND=y
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/config/common_linuxapp b/config/common_linuxapp
index 4713eb4..66d2ce1 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -252,6 +252,11 @@ CONFIG_RTE_LIBRTE_PMD_BOND=y
 CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/lib/Makefile b/lib/Makefile
index 10c5bb3..61d6ed1 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -50,6 +50,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += librte_pmd_pcap
 DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += librte_pmd_virtio
 DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt
+DIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += librte_pmd_null
 DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash
 DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm
 DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl
diff --git a/lib/librte_pmd_null/Makefile b/lib/librte_pmd_null/Makefile
new file mode 100644
index 0000000..e017918
--- /dev/null
+++ b/lib/librte_pmd_null/Makefile
@@ -0,0 +1,58 @@
+#   BSD LICENSE
+#
+#   Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
+#   All rights reserved.
+#
+#   Redistribution and use in source and binary forms, with or without
+#   modification, are permitted provided that the following conditions
+#   are met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in
+#       the documentation and/or other materials provided with the
+#       distribution.
+#     * Neither the name of Intel Corporation nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_pmd_null.a
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += rte_eth_null.c
+
+#
+# Export include files
+#
+SYMLINK-y-include +=
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_malloc
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_kvargs
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
new file mode 100644
index 0000000..7ecdd17
--- /dev/null
+++ b/lib/librte_pmd_null/rte_eth_null.c
@@ -0,0 +1,474 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright (C) IGEL Co.,Ltd.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of IGEL Co.,Ltd. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_dev.h>
+#include <rte_kvargs.h>
+
+#define ETH_NULL_PACKET_SIZE_ARG	"size"
+#define ETH_NULL_PACKET_COPY_ARG	"copy"
+
+static unsigned default_packet_size = 64;
+static unsigned default_packet_copy;
+
+static const char const *valid_arguments[] = {
+	ETH_NULL_PACKET_SIZE_ARG,
+	ETH_NULL_PACKET_COPY_ARG,
+	NULL
+};
+
+struct pmd_internals;
+
+struct null_queue {
+	struct pmd_internals *internals;
+
+	struct rte_mempool *mb_pool;
+	struct rte_mbuf *dummy_packet;
+
+	rte_atomic64_t rx_pkts;
+	rte_atomic64_t tx_pkts;
+	rte_atomic64_t err_pkts;
+};
+
+struct pmd_internals {
+	unsigned packet_size;
+	unsigned packet_copy;
+	unsigned numa_node;
+
+	unsigned nb_rx_queues;
+	unsigned nb_tx_queues;
+
+	struct null_queue rx_null_queues[1];
+	struct null_queue tx_null_queues[1];
+};
+
+
+static struct ether_addr eth_addr = { .addr_bytes = {0} };
+static const char *drivername = "Null PMD";
+static struct rte_eth_link pmd_link = {
+	.link_speed = 10000,
+	.link_duplex = ETH_LINK_FULL_DUPLEX,
+	.link_status = 0
+};
+
+static uint16_t
+eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,
+					packet_size);
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_tx(void *q, struct rte_mbuf **bufs __rte_unused, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+
+	for (i = 0; i < nb_bufs; i++)
+		rte_pktmbuf_free(bufs[i]);
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	for (i = 0; i < nb_bufs; i++) {
+		rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *),
+					packet_size);
+		rte_pktmbuf_free(bufs[i]);
+	}
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static int
+eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; }
+
+static int
+eth_dev_start(struct rte_eth_dev *dev)
+{
+	dev->data->dev_link.link_status = 1;
+	return 0;
+}
+
+static void
+eth_dev_stop(struct rte_eth_dev *dev)
+{
+	dev->data->dev_link.link_status = 0;
+}
+
+static int
+eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+		uint16_t nb_rx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_rxconf *rx_conf __rte_unused,
+		struct rte_mempool *mb_pool __rte_unused)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals = dev->data->dev_private;
+	unsigned packet_size = internals->packet_size;
+
+	if (rx_queue_id != 0)
+			return -ENODEV;
+
+	internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool;
+	dev->data->rx_queues[rx_queue_id] =
+		&internals->rx_null_queues[rx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->rx_null_queues[rx_queue_id].internals = internals;
+	internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+static int
+eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+		uint16_t nb_tx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals = dev->data->dev_private;
+	unsigned packet_size = internals->packet_size;
+
+	if (tx_queue_id != 0)
+			return -ENODEV;
+
+	dev->data->tx_queues[tx_queue_id] =
+		&internals->tx_null_queues[tx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->tx_null_queues[tx_queue_id].internals = internals;
+	internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+
+static void
+eth_dev_info(struct rte_eth_dev *dev,
+		struct rte_eth_dev_info *dev_info)
+{
+	struct pmd_internals *internals = dev->data->dev_private;
+
+	dev_info->driver_name = drivername;
+	dev_info->max_mac_addrs = 1;
+	dev_info->max_rx_pktlen = (uint32_t)-1;
+	dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;
+	dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;
+	dev_info->min_rx_bufsize = 0;
+	dev_info->pci_dev = NULL;
+}
+
+static void
+eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)
+{
+	unsigned i;
+	unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
+	const struct pmd_internals *internal = dev->data->dev_private;
+
+	memset(igb_stats, 0, sizeof(*igb_stats));
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_rx_queues; i++) {
+		igb_stats->q_ipackets[i] =
+			internal->rx_null_queues[i].rx_pkts.cnt;
+		rx_total += igb_stats->q_ipackets[i];
+	}
+
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_tx_queues; i++) {
+		igb_stats->q_opackets[i] =
+			internal->tx_null_queues[i].tx_pkts.cnt;
+		igb_stats->q_errors[i] =
+			internal->tx_null_queues[i].err_pkts.cnt;
+		tx_total += igb_stats->q_opackets[i];
+		tx_err_total += igb_stats->q_errors[i];
+	}
+
+	igb_stats->ipackets = rx_total;
+	igb_stats->opackets = tx_total;
+	igb_stats->oerrors = tx_err_total;
+}
+
+static void
+eth_stats_reset(struct rte_eth_dev *dev)
+{
+	unsigned i;
+	struct pmd_internals *internal = dev->data->dev_private;
+
+	for (i = 0; i < internal->nb_rx_queues; i++)
+		internal->rx_null_queues[i].rx_pkts.cnt = 0;
+	for (i = 0; i < internal->nb_tx_queues; i++) {
+		internal->tx_null_queues[i].tx_pkts.cnt = 0;
+		internal->tx_null_queues[i].err_pkts.cnt = 0;
+	}
+}
+
+static void
+eth_queue_release(void *q __rte_unused) { ; }
+static int
+eth_link_update(struct rte_eth_dev *dev __rte_unused,
+		int wait_to_complete __rte_unused) { return 0; }
+
+static struct eth_dev_ops ops = {
+		.dev_start = eth_dev_start,
+		.dev_stop = eth_dev_stop,
+		.dev_configure = eth_dev_configure,
+		.dev_infos_get = eth_dev_info,
+		.rx_queue_setup = eth_rx_queue_setup,
+		.tx_queue_setup = eth_tx_queue_setup,
+		.rx_queue_release = eth_queue_release,
+		.tx_queue_release = eth_queue_release,
+		.link_update = eth_link_update,
+		.stats_get = eth_stats_get,
+		.stats_reset = eth_stats_reset,
+};
+
+static int
+eth_dev_null_create(const char *name __rte_unused,
+		const unsigned numa_node,
+		unsigned packet_size,
+		unsigned packet_copy)
+{
+	const unsigned nb_rx_queues = 1;
+	const unsigned nb_tx_queues = 1;
+	struct rte_eth_dev_data *data = NULL;
+	struct rte_pci_device *pci_dev = NULL;
+	struct pmd_internals *internals = NULL;
+	struct rte_eth_dev *eth_dev = NULL;
+
+	RTE_LOG(INFO, PMD, "Creating null ethdev on numa socket %u\n",
+			numa_node);
+
+	/* now do all data allocation - for eth_dev structure, dummy pci driver
+	 * and internal (private) data
+	 */
+	data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);
+	if (data == NULL)
+		goto error;
+
+	pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);
+	if (pci_dev == NULL)
+		goto error;
+
+	internals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node);
+	if (internals == NULL)
+		goto error;
+
+	/* reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocate(name);
+	if (eth_dev == NULL)
+		goto error;
+
+	/* now put it all together
+	 * - store queue data in internals,
+	 * - store numa_node info in pci_driver
+	 * - point eth_dev_data to internals and pci_driver
+	 * - and point eth_dev structure to new eth_dev_data structure
+	 */
+	/* NOTE: we'll replace the data element, of originally allocated eth_dev
+	 * so the nulls are local per-process */
+
+	internals->nb_rx_queues = nb_rx_queues;
+	internals->nb_tx_queues = nb_tx_queues;
+	internals->packet_size = packet_size;
+	internals->packet_copy = packet_copy;
+	internals->numa_node = numa_node;
+
+	pci_dev->numa_node = numa_node;
+
+	data->dev_private = internals;
+	data->port_id = eth_dev->data->port_id;
+	data->nb_rx_queues = (uint16_t)nb_rx_queues;
+	data->nb_tx_queues = (uint16_t)nb_tx_queues;
+	data->dev_link = pmd_link;
+	data->mac_addrs = &eth_addr;
+
+	eth_dev->data = data;
+	eth_dev->dev_ops = &ops;
+	eth_dev->pci_dev = pci_dev;
+
+	/* finally assign rx and tx ops */
+	if (packet_copy) {
+		eth_dev->rx_pkt_burst = eth_null_copy_rx;
+		eth_dev->tx_pkt_burst = eth_null_copy_tx;
+	} else {
+		eth_dev->rx_pkt_burst = eth_null_rx;
+		eth_dev->tx_pkt_burst = eth_null_tx;
+	}
+
+	return 0;
+
+error:
+	if (data)
+		rte_free(data);
+	if (pci_dev)
+		rte_free(pci_dev);
+	if (internals)
+		rte_free(internals);
+	return -1;
+}
+
+static inline int
+get_packet_size_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_size = extra_args;
+
+	*packet_size = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_size == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static inline int
+get_packet_copy_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_copy = extra_args;
+
+	*packet_copy = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_copy == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static int
+rte_pmd_null_devinit(const char *name, const char *params)
+{
+	unsigned numa_node;
+	unsigned packet_size = default_packet_size;
+	unsigned packet_copy = default_packet_copy;
+	struct rte_kvargs *kvlist;
+	int ret;
+
+	RTE_LOG(INFO, PMD, "Initializing pmd_null for %s\n", name);
+
+	numa_node = rte_socket_id();
+
+	kvlist = rte_kvargs_parse(params, valid_arguments);
+	if (kvlist == NULL)
+		return -1;
+
+	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) {
+
+		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_SIZE_ARG,
+				&get_packet_size_arg, &packet_size);
+		if (ret < 0)
+			return -1;
+	}
+
+	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) {
+
+		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_COPY_ARG,
+				&get_packet_copy_arg, &packet_copy);
+		if (ret < 0)
+			return -1;
+	}
+
+	RTE_LOG(INFO, PMD, "Configure pmd_null: packet size is %d, "
+			"packet copy is %s\n", packet_size,
+			packet_copy ? "enabled" : "disabled");
+
+	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
+}
+
+static struct rte_driver pmd_null_drv = {
+	.name = "eth_null",
+	.type = PMD_VDEV,
+	.init = rte_pmd_null_devinit,
+};
+
+PMD_REGISTER_DRIVER(pmd_null_drv);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH 2/2] librte_pmd_null: Enable librte_pmd_null
       [not found]   ` <1412070970-5625-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  2014-09-30  9:56     ` [PATCH 1/2] librte_pmd_null: Add null PMD mukawa-AlSX/UN32fvPDbFq/vQRIQ
@ 2014-09-30  9:56     ` mukawa-AlSX/UN32fvPDbFq/vQRIQ
       [not found]       ` <1412070970-5625-3-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  1 sibling, 1 reply; 60+ messages in thread
From: mukawa-AlSX/UN32fvPDbFq/vQRIQ @ 2014-09-30  9:56 UTC (permalink / raw)
  To: dev-VfR2kkLFssw
  Cc: nakajima.yoshihiro-Zyj7fXuS5i5L9jVzuh4AOg,
	masutani.hitoshi-Zyj7fXuS5i5L9jVzuh4AOg

From: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>

Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
---
 mk/rte.app.mk | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 34dff2a..f059290 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -179,6 +179,10 @@ LDLIBS += -lrte_pmd_xenvirt
 LDLIBS += -lxenstore
 endif
 
+ifeq ($(CONFIG_RTE_LIBRTE_PMD_NULL),y)
+LDLIBS += -lrte_pmd_null
+endif
+
 ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),n)
 # plugins (link only if static libraries)
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* Re: [PATCH 2/2] librte_pmd_null: Enable librte_pmd_null
       [not found]       ` <1412070970-5625-3-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2014-09-30 11:23         ` Neil Horman
       [not found]           ` <20140930112353.GA2193-B26myB8xz7F8NnZeBjwnZQMhkBWG/bsMQH7oEaQurus@public.gmane.org>
  0 siblings, 1 reply; 60+ messages in thread
From: Neil Horman @ 2014-09-30 11:23 UTC (permalink / raw)
  To: mukawa-AlSX/UN32fvPDbFq/vQRIQ
  Cc: dev-VfR2kkLFssw, nakajima.yoshihiro-Zyj7fXuS5i5L9jVzuh4AOg,
	masutani.hitoshi-Zyj7fXuS5i5L9jVzuh4AOg

On Tue, Sep 30, 2014 at 06:56:10PM +0900, mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org wrote:
> From: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
> 
> Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
> ---
>  mk/rte.app.mk | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/mk/rte.app.mk b/mk/rte.app.mk
> index 34dff2a..f059290 100644
> --- a/mk/rte.app.mk
> +++ b/mk/rte.app.mk
> @@ -179,6 +179,10 @@ LDLIBS += -lrte_pmd_xenvirt
>  LDLIBS += -lxenstore
>  endif
>  
> +ifeq ($(CONFIG_RTE_LIBRTE_PMD_NULL),y)
> +LDLIBS += -lrte_pmd_null
> +endif
> +
You don't need to add this, as the pmd can be loaded dynamically via the dlopen
call executed via the -d option on the test app command line.  The only pmds
that need explicit linking are those that offer additional API calls to an
appilcation.

Neil

>  ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),n)
>  # plugins (link only if static libraries)
>  
> -- 
> 1.9.1
> 
> 

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH 1/2] librte_pmd_null: Add null PMD
       [not found]       ` <1412070970-5625-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2014-09-30 13:05         ` Thomas Monjalon
  2014-10-01  1:41           ` Tetsuya Mukawa
  0 siblings, 1 reply; 60+ messages in thread
From: Thomas Monjalon @ 2014-09-30 13:05 UTC (permalink / raw)
  To: mukawa-AlSX/UN32fvPDbFq/vQRIQ
  Cc: dev-VfR2kkLFssw, nakajima.yoshihiro-Zyj7fXuS5i5L9jVzuh4AOg,
	masutani.hitoshi-Zyj7fXuS5i5L9jVzuh4AOg

2014-09-30 18:56, mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org:
> --- /dev/null
> +++ b/lib/librte_pmd_null/Makefile
> @@ -0,0 +1,58 @@
> +#   BSD LICENSE
> +#
> +#   Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
> +#   All rights reserved.
> +#
> +#   Redistribution and use in source and binary forms, with or without
> +#   modification, are permitted provided that the following conditions
> +#   are met:
> +#
> +#     * Redistributions of source code must retain the above copyright
> +#       notice, this list of conditions and the following disclaimer.
> +#     * Redistributions in binary form must reproduce the above copyright
> +#       notice, this list of conditions and the following disclaimer in
> +#       the documentation and/or other materials provided with the
> +#       distribution.
> +#     * Neither the name of Intel Corporation nor the names of its

You probably mean NTT here?

> --- /dev/null
> +++ b/lib/librte_pmd_null/rte_eth_null.c
> @@ -0,0 +1,474 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright (C) IGEL Co.,Ltd.
> + *   All rights reserved.
> + *
> + *   Redistribution and use in source and binary forms, with or without
> + *   modification, are permitted provided that the following conditions
> + *   are met:
> + *
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in
> + *       the documentation and/or other materials provided with the
> + *       distribution.
> + *     * Neither the name of IGEL Co.,Ltd. nor the names of its
> + *       contributors may be used to endorse or promote products derived
> + *       from this software without specific prior written permission.

So the Makefile is copyrighted NTT and the .c file is copyrighted IGEL?

-- 
Thomas

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH 2/2] librte_pmd_null: Enable librte_pmd_null
       [not found]           ` <20140930112353.GA2193-B26myB8xz7F8NnZeBjwnZQMhkBWG/bsMQH7oEaQurus@public.gmane.org>
@ 2014-10-01  1:39             ` Tetsuya Mukawa
  0 siblings, 0 replies; 60+ messages in thread
From: Tetsuya Mukawa @ 2014-10-01  1:39 UTC (permalink / raw)
  To: Neil Horman
  Cc: dev-VfR2kkLFssw, nakajima.yoshihiro-Zyj7fXuS5i5L9jVzuh4AOg,
	masutani.hitoshi-Zyj7fXuS5i5L9jVzuh4AOg

(2014/09/30 20:23), Neil Horman wrote:
> On Tue, Sep 30, 2014 at 06:56:10PM +0900, mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org wrote:
>> From: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
>>
>> Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
>> ---
>>  mk/rte.app.mk | 4 ++++
>>  1 file changed, 4 insertions(+)
>>
>> diff --git a/mk/rte.app.mk b/mk/rte.app.mk
>> index 34dff2a..f059290 100644
>> --- a/mk/rte.app.mk
>> +++ b/mk/rte.app.mk
>> @@ -179,6 +179,10 @@ LDLIBS += -lrte_pmd_xenvirt
>>  LDLIBS += -lxenstore
>>  endif
>>  
>> +ifeq ($(CONFIG_RTE_LIBRTE_PMD_NULL),y)
>> +LDLIBS += -lrte_pmd_null
>> +endif
>> +
> You don't need to add this, as the pmd can be loaded dynamically via the dlopen
> call executed via the -d option on the test app command line.  The only pmds
> that need explicit linking are those that offer additional API calls to an
> appilcation.
Thanks, I will change above.

Regards,
Tetsuya


> Neil
>
>>  ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),n)
>>  # plugins (link only if static libraries)
>>  
>> -- 
>> 1.9.1
>>
>>

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH 1/2] librte_pmd_null: Add null PMD
  2014-09-30 13:05         ` Thomas Monjalon
@ 2014-10-01  1:41           ` Tetsuya Mukawa
  0 siblings, 0 replies; 60+ messages in thread
From: Tetsuya Mukawa @ 2014-10-01  1:41 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: dev-VfR2kkLFssw, nakajima.yoshihiro-Zyj7fXuS5i5L9jVzuh4AOg,
	masutani.hitoshi-Zyj7fXuS5i5L9jVzuh4AOg

(2014/09/30 22:05), Thomas Monjalon wrote:
> 2014-09-30 18:56, mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org:
>> --- /dev/null
>> +++ b/lib/librte_pmd_null/Makefile
>> @@ -0,0 +1,58 @@
>> +#   BSD LICENSE
>> +#
>> +#   Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
>> +#   All rights reserved.
>> +#
>> +#   Redistribution and use in source and binary forms, with or without
>> +#   modification, are permitted provided that the following conditions
>> +#   are met:
>> +#
>> +#     * Redistributions of source code must retain the above copyright
>> +#       notice, this list of conditions and the following disclaimer.
>> +#     * Redistributions in binary form must reproduce the above copyright
>> +#       notice, this list of conditions and the following disclaimer in
>> +#       the documentation and/or other materials provided with the
>> +#       distribution.
>> +#     * Neither the name of Intel Corporation nor the names of its
> You probably mean NTT here?
>
>> --- /dev/null
>> +++ b/lib/librte_pmd_null/rte_eth_null.c
>> @@ -0,0 +1,474 @@
>> +/*-
>> + *   BSD LICENSE
>> + *
>> + *   Copyright (C) IGEL Co.,Ltd.
>> + *   All rights reserved.
>> + *
>> + *   Redistribution and use in source and binary forms, with or without
>> + *   modification, are permitted provided that the following conditions
>> + *   are met:
>> + *
>> + *     * Redistributions of source code must retain the above copyright
>> + *       notice, this list of conditions and the following disclaimer.
>> + *     * Redistributions in binary form must reproduce the above copyright
>> + *       notice, this list of conditions and the following disclaimer in
>> + *       the documentation and/or other materials provided with the
>> + *       distribution.
>> + *     * Neither the name of IGEL Co.,Ltd. nor the names of its
>> + *       contributors may be used to endorse or promote products derived
>> + *       from this software without specific prior written permission.
> So the Makefile is copyrighted NTT and the .c file is copyrighted IGEL?
>
It's my mistake. I needed to change Makefile also.
I had a discussion about copyright with NTT guys, then changed it.
Thank you for your attention. I will submit again.

Regards,
Tetsuya

^ permalink raw reply	[flat|nested] 60+ messages in thread

* [PATCH] Fix linking errors when CONFIG_RTE_BUILD_SHARED_LIB is enabled
       [not found] <mukawa@igel.co.jp>
  2014-09-19 12:27 ` [RFC] PMD for performance measurement mukawa-AlSX/UN32fvPDbFq/vQRIQ
  2014-09-30  9:56 ` [PATCH 0/2] PMD for performance measurement mukawa-AlSX/UN32fvPDbFq/vQRIQ
@ 2014-10-01  4:27 ` mukawa-AlSX/UN32fvPDbFq/vQRIQ
       [not found]   ` <1412137623-18817-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  2014-10-01  4:57 ` [PATCH v2] PMD for performance measurement mukawa-AlSX/UN32fvPDbFq/vQRIQ
  3 siblings, 1 reply; 60+ messages in thread
From: mukawa-AlSX/UN32fvPDbFq/vQRIQ @ 2014-10-01  4:27 UTC (permalink / raw)
  To: dev-VfR2kkLFssw

From: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>

When CONFIG_RTE_BUILD_SHARED_LIB is enabled, linking errors occured
while compiling. It seems those errors are caused by wrong link order
of some libraries. The patch fixes it like following.

1. librte_eal
2. librte_malloc
3. librte_mempool
4. librte_ring
5. librte_pmd_bond
6. librte_kvargs

Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
---
 mk/rte.app.mk | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 34dff2a..172ba4d 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -121,10 +121,6 @@ endif
 
 LDLIBS += --start-group
 
-ifeq ($(CONFIG_RTE_LIBRTE_KVARGS),y)
-LDLIBS += -lrte_kvargs
-endif
-
 ifeq ($(CONFIG_RTE_LIBRTE_MBUF),y)
 LDLIBS += -lrte_mbuf
 endif
@@ -137,6 +133,10 @@ ifeq ($(CONFIG_RTE_LIBRTE_ETHER),y)
 LDLIBS += -lethdev
 endif
 
+ifeq ($(CONFIG_RTE_LIBRTE_EAL),y)
+LDLIBS += -lrte_eal
+endif
+
 ifeq ($(CONFIG_RTE_LIBRTE_MALLOC),y)
 LDLIBS += -lrte_malloc
 endif
@@ -158,10 +158,6 @@ ifeq ($(CONFIG_RTE_LIBGLOSS),y)
 LDLIBS += -lgloss
 endif
 
-ifeq ($(CONFIG_RTE_LIBRTE_EAL),y)
-LDLIBS += -lrte_eal
-endif
-
 ifeq ($(CONFIG_RTE_LIBRTE_CMDLINE),y)
 LDLIBS += -lrte_cmdline
 endif
@@ -174,6 +170,10 @@ ifeq ($(CONFIG_RTE_LIBRTE_PMD_BOND),y)
 LDLIBS += -lrte_pmd_bond
 endif
 
+ifeq ($(CONFIG_RTE_LIBRTE_KVARGS),y)
+LDLIBS += -lrte_kvargs
+endif
+
 ifeq ($(CONFIG_RTE_LIBRTE_PMD_XENVIRT),y)
 LDLIBS += -lrte_pmd_xenvirt
 LDLIBS += -lxenstore
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v2] PMD for performance measurement
       [not found] <mukawa@igel.co.jp>
                   ` (2 preceding siblings ...)
  2014-10-01  4:27 ` [PATCH] Fix linking errors when CONFIG_RTE_BUILD_SHARED_LIB is enabled mukawa-AlSX/UN32fvPDbFq/vQRIQ
@ 2014-10-01  4:57 ` mukawa-AlSX/UN32fvPDbFq/vQRIQ
       [not found]   ` <1412139437-26749-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  3 siblings, 1 reply; 60+ messages in thread
From: mukawa-AlSX/UN32fvPDbFq/vQRIQ @ 2014-10-01  4:57 UTC (permalink / raw)
  To: dev-VfR2kkLFssw
  Cc: nakajima.yoshihiro-Zyj7fXuS5i5L9jVzuh4AOg,
	masutani.hitoshi-Zyj7fXuS5i5L9jVzuh4AOg

From: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>

Hi,

Here are patches to add the new PMD like '/dev/null'.
This PMD is a driver for virtual device. When an application call rx,
it just allocates mbufs and returns those. Also tx, it just frees mbufs.

Main purpose of the PMD is measuring rough throughputs of a VDEV PMD.
To measure rough throughputs between PMD1 and PMD2, prepare following
environment.

+-------------------------------+
|           testpmd1            |
+-------------+------+----------+
| Target PMD1 |      | null PMD |
+---++--------+      +----------+
    ||
    || Target path
    ||
+---++--------+      +----------+
| Target PMD2 |      | null PMD |
+-------------+------+----------+
|           testpmd2            |
+-------------------------------+

changes from v1:
* change the copyright of Makefile.
* change commit log.
* change config file not to link the PMD statically.

changes from RFC:
* change the copyright of this PMD.
* change commit logs.

Tetsuya Mukawa (1):
  librte_pmd_null: Add null PMD

 config/common_bsdapp               |   5 +
 config/common_linuxapp             |   5 +
 lib/Makefile                       |   1 +
 lib/librte_pmd_null/Makefile       |  58 +++++
 lib/librte_pmd_null/rte_eth_null.c | 474 +++++++++++++++++++++++++++++++++++++
 5 files changed, 543 insertions(+)
 create mode 100644 lib/librte_pmd_null/Makefile
 create mode 100644 lib/librte_pmd_null/rte_eth_null.c

-- 
1.9.1

^ permalink raw reply	[flat|nested] 60+ messages in thread

* [PATCH v2] librte_pmd_null: Add null PMD
       [not found]   ` <1412139437-26749-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2014-10-01  4:57     ` mukawa-AlSX/UN32fvPDbFq/vQRIQ
       [not found]       ` <1412139437-26749-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  0 siblings, 1 reply; 60+ messages in thread
From: mukawa-AlSX/UN32fvPDbFq/vQRIQ @ 2014-10-01  4:57 UTC (permalink / raw)
  To: dev-VfR2kkLFssw
  Cc: nakajima.yoshihiro-Zyj7fXuS5i5L9jVzuh4AOg,
	masutani.hitoshi-Zyj7fXuS5i5L9jVzuh4AOg

From: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>

'null PMD' is a driver of the virtual device particulary designed to measure
performance of DPDK PMDs. When an application call rx, null PMD just allocates
mbufs and returns those. Also tx, the PMD just frees mbufs.

The PMD has following options.
- size: specify packe size allocated by RX. Default packet size is 64.
- copy: specify 1 or 0 to enable or disable copy while RX and TX.
	Default value is 0(disbaled).
	This option is used for emulating more realistic data transfer.
	Copy size is equal to packet size.

To use the PMD, enable CONFIG_RTE_BUILD_SHARED_LIB in config file. Then
compile the PMD as shared library. The library can be linked using '-d'
option when an application invokes.

Here is an example.
$ sudo ./testpmd -c f -n 4 -d librte_pmd_null.so \
	--vdev 'eth_null0' --vdev 'eth_null1' -- -i

If testpmd is compiled with CONFIG_RTE_BUILD_SHARED_LIB, it may need to
specify more libraries using '-d' option.

Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
---
 config/common_bsdapp               |   5 +
 config/common_linuxapp             |   5 +
 lib/Makefile                       |   1 +
 lib/librte_pmd_null/Makefile       |  58 +++++
 lib/librte_pmd_null/rte_eth_null.c | 474 +++++++++++++++++++++++++++++++++++++
 5 files changed, 543 insertions(+)
 create mode 100644 lib/librte_pmd_null/Makefile
 create mode 100644 lib/librte_pmd_null/rte_eth_null.c

diff --git a/config/common_bsdapp b/config/common_bsdapp
index eebd05b..bda37f5 100644
--- a/config/common_bsdapp
+++ b/config/common_bsdapp
@@ -224,6 +224,11 @@ CONFIG_RTE_LIBRTE_PMD_PCAP=y
 CONFIG_RTE_LIBRTE_PMD_BOND=y
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/config/common_linuxapp b/config/common_linuxapp
index 4713eb4..66d2ce1 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -252,6 +252,11 @@ CONFIG_RTE_LIBRTE_PMD_BOND=y
 CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/lib/Makefile b/lib/Makefile
index 10c5bb3..61d6ed1 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -50,6 +50,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += librte_pmd_pcap
 DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += librte_pmd_virtio
 DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt
+DIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += librte_pmd_null
 DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash
 DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm
 DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl
diff --git a/lib/librte_pmd_null/Makefile b/lib/librte_pmd_null/Makefile
new file mode 100644
index 0000000..0ec4db9
--- /dev/null
+++ b/lib/librte_pmd_null/Makefile
@@ -0,0 +1,58 @@
+#   BSD LICENSE
+#
+#   Copyright (C) IGEL Co.,Ltd.
+#   All rights reserved.
+#
+#   Redistribution and use in source and binary forms, with or without
+#   modification, are permitted provided that the following conditions
+#   are met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in
+#       the documentation and/or other materials provided with the
+#       distribution.
+#     * Neither the name of IGEL Co.,Ltd. nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_pmd_null.a
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += rte_eth_null.c
+
+#
+# Export include files
+#
+SYMLINK-y-include +=
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_malloc
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_kvargs
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
new file mode 100644
index 0000000..7ecdd17
--- /dev/null
+++ b/lib/librte_pmd_null/rte_eth_null.c
@@ -0,0 +1,474 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright (C) IGEL Co.,Ltd.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of IGEL Co.,Ltd. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_dev.h>
+#include <rte_kvargs.h>
+
+#define ETH_NULL_PACKET_SIZE_ARG	"size"
+#define ETH_NULL_PACKET_COPY_ARG	"copy"
+
+static unsigned default_packet_size = 64;
+static unsigned default_packet_copy;
+
+static const char const *valid_arguments[] = {
+	ETH_NULL_PACKET_SIZE_ARG,
+	ETH_NULL_PACKET_COPY_ARG,
+	NULL
+};
+
+struct pmd_internals;
+
+struct null_queue {
+	struct pmd_internals *internals;
+
+	struct rte_mempool *mb_pool;
+	struct rte_mbuf *dummy_packet;
+
+	rte_atomic64_t rx_pkts;
+	rte_atomic64_t tx_pkts;
+	rte_atomic64_t err_pkts;
+};
+
+struct pmd_internals {
+	unsigned packet_size;
+	unsigned packet_copy;
+	unsigned numa_node;
+
+	unsigned nb_rx_queues;
+	unsigned nb_tx_queues;
+
+	struct null_queue rx_null_queues[1];
+	struct null_queue tx_null_queues[1];
+};
+
+
+static struct ether_addr eth_addr = { .addr_bytes = {0} };
+static const char *drivername = "Null PMD";
+static struct rte_eth_link pmd_link = {
+	.link_speed = 10000,
+	.link_duplex = ETH_LINK_FULL_DUPLEX,
+	.link_status = 0
+};
+
+static uint16_t
+eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,
+					packet_size);
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_tx(void *q, struct rte_mbuf **bufs __rte_unused, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+
+	for (i = 0; i < nb_bufs; i++)
+		rte_pktmbuf_free(bufs[i]);
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	for (i = 0; i < nb_bufs; i++) {
+		rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *),
+					packet_size);
+		rte_pktmbuf_free(bufs[i]);
+	}
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static int
+eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; }
+
+static int
+eth_dev_start(struct rte_eth_dev *dev)
+{
+	dev->data->dev_link.link_status = 1;
+	return 0;
+}
+
+static void
+eth_dev_stop(struct rte_eth_dev *dev)
+{
+	dev->data->dev_link.link_status = 0;
+}
+
+static int
+eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+		uint16_t nb_rx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_rxconf *rx_conf __rte_unused,
+		struct rte_mempool *mb_pool __rte_unused)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals = dev->data->dev_private;
+	unsigned packet_size = internals->packet_size;
+
+	if (rx_queue_id != 0)
+			return -ENODEV;
+
+	internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool;
+	dev->data->rx_queues[rx_queue_id] =
+		&internals->rx_null_queues[rx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->rx_null_queues[rx_queue_id].internals = internals;
+	internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+static int
+eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+		uint16_t nb_tx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals = dev->data->dev_private;
+	unsigned packet_size = internals->packet_size;
+
+	if (tx_queue_id != 0)
+			return -ENODEV;
+
+	dev->data->tx_queues[tx_queue_id] =
+		&internals->tx_null_queues[tx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->tx_null_queues[tx_queue_id].internals = internals;
+	internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+
+static void
+eth_dev_info(struct rte_eth_dev *dev,
+		struct rte_eth_dev_info *dev_info)
+{
+	struct pmd_internals *internals = dev->data->dev_private;
+
+	dev_info->driver_name = drivername;
+	dev_info->max_mac_addrs = 1;
+	dev_info->max_rx_pktlen = (uint32_t)-1;
+	dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;
+	dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;
+	dev_info->min_rx_bufsize = 0;
+	dev_info->pci_dev = NULL;
+}
+
+static void
+eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)
+{
+	unsigned i;
+	unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
+	const struct pmd_internals *internal = dev->data->dev_private;
+
+	memset(igb_stats, 0, sizeof(*igb_stats));
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_rx_queues; i++) {
+		igb_stats->q_ipackets[i] =
+			internal->rx_null_queues[i].rx_pkts.cnt;
+		rx_total += igb_stats->q_ipackets[i];
+	}
+
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_tx_queues; i++) {
+		igb_stats->q_opackets[i] =
+			internal->tx_null_queues[i].tx_pkts.cnt;
+		igb_stats->q_errors[i] =
+			internal->tx_null_queues[i].err_pkts.cnt;
+		tx_total += igb_stats->q_opackets[i];
+		tx_err_total += igb_stats->q_errors[i];
+	}
+
+	igb_stats->ipackets = rx_total;
+	igb_stats->opackets = tx_total;
+	igb_stats->oerrors = tx_err_total;
+}
+
+static void
+eth_stats_reset(struct rte_eth_dev *dev)
+{
+	unsigned i;
+	struct pmd_internals *internal = dev->data->dev_private;
+
+	for (i = 0; i < internal->nb_rx_queues; i++)
+		internal->rx_null_queues[i].rx_pkts.cnt = 0;
+	for (i = 0; i < internal->nb_tx_queues; i++) {
+		internal->tx_null_queues[i].tx_pkts.cnt = 0;
+		internal->tx_null_queues[i].err_pkts.cnt = 0;
+	}
+}
+
+static void
+eth_queue_release(void *q __rte_unused) { ; }
+static int
+eth_link_update(struct rte_eth_dev *dev __rte_unused,
+		int wait_to_complete __rte_unused) { return 0; }
+
+static struct eth_dev_ops ops = {
+		.dev_start = eth_dev_start,
+		.dev_stop = eth_dev_stop,
+		.dev_configure = eth_dev_configure,
+		.dev_infos_get = eth_dev_info,
+		.rx_queue_setup = eth_rx_queue_setup,
+		.tx_queue_setup = eth_tx_queue_setup,
+		.rx_queue_release = eth_queue_release,
+		.tx_queue_release = eth_queue_release,
+		.link_update = eth_link_update,
+		.stats_get = eth_stats_get,
+		.stats_reset = eth_stats_reset,
+};
+
+static int
+eth_dev_null_create(const char *name __rte_unused,
+		const unsigned numa_node,
+		unsigned packet_size,
+		unsigned packet_copy)
+{
+	const unsigned nb_rx_queues = 1;
+	const unsigned nb_tx_queues = 1;
+	struct rte_eth_dev_data *data = NULL;
+	struct rte_pci_device *pci_dev = NULL;
+	struct pmd_internals *internals = NULL;
+	struct rte_eth_dev *eth_dev = NULL;
+
+	RTE_LOG(INFO, PMD, "Creating null ethdev on numa socket %u\n",
+			numa_node);
+
+	/* now do all data allocation - for eth_dev structure, dummy pci driver
+	 * and internal (private) data
+	 */
+	data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);
+	if (data == NULL)
+		goto error;
+
+	pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);
+	if (pci_dev == NULL)
+		goto error;
+
+	internals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node);
+	if (internals == NULL)
+		goto error;
+
+	/* reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocate(name);
+	if (eth_dev == NULL)
+		goto error;
+
+	/* now put it all together
+	 * - store queue data in internals,
+	 * - store numa_node info in pci_driver
+	 * - point eth_dev_data to internals and pci_driver
+	 * - and point eth_dev structure to new eth_dev_data structure
+	 */
+	/* NOTE: we'll replace the data element, of originally allocated eth_dev
+	 * so the nulls are local per-process */
+
+	internals->nb_rx_queues = nb_rx_queues;
+	internals->nb_tx_queues = nb_tx_queues;
+	internals->packet_size = packet_size;
+	internals->packet_copy = packet_copy;
+	internals->numa_node = numa_node;
+
+	pci_dev->numa_node = numa_node;
+
+	data->dev_private = internals;
+	data->port_id = eth_dev->data->port_id;
+	data->nb_rx_queues = (uint16_t)nb_rx_queues;
+	data->nb_tx_queues = (uint16_t)nb_tx_queues;
+	data->dev_link = pmd_link;
+	data->mac_addrs = &eth_addr;
+
+	eth_dev->data = data;
+	eth_dev->dev_ops = &ops;
+	eth_dev->pci_dev = pci_dev;
+
+	/* finally assign rx and tx ops */
+	if (packet_copy) {
+		eth_dev->rx_pkt_burst = eth_null_copy_rx;
+		eth_dev->tx_pkt_burst = eth_null_copy_tx;
+	} else {
+		eth_dev->rx_pkt_burst = eth_null_rx;
+		eth_dev->tx_pkt_burst = eth_null_tx;
+	}
+
+	return 0;
+
+error:
+	if (data)
+		rte_free(data);
+	if (pci_dev)
+		rte_free(pci_dev);
+	if (internals)
+		rte_free(internals);
+	return -1;
+}
+
+static inline int
+get_packet_size_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_size = extra_args;
+
+	*packet_size = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_size == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static inline int
+get_packet_copy_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_copy = extra_args;
+
+	*packet_copy = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_copy == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static int
+rte_pmd_null_devinit(const char *name, const char *params)
+{
+	unsigned numa_node;
+	unsigned packet_size = default_packet_size;
+	unsigned packet_copy = default_packet_copy;
+	struct rte_kvargs *kvlist;
+	int ret;
+
+	RTE_LOG(INFO, PMD, "Initializing pmd_null for %s\n", name);
+
+	numa_node = rte_socket_id();
+
+	kvlist = rte_kvargs_parse(params, valid_arguments);
+	if (kvlist == NULL)
+		return -1;
+
+	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) {
+
+		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_SIZE_ARG,
+				&get_packet_size_arg, &packet_size);
+		if (ret < 0)
+			return -1;
+	}
+
+	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) {
+
+		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_COPY_ARG,
+				&get_packet_copy_arg, &packet_copy);
+		if (ret < 0)
+			return -1;
+	}
+
+	RTE_LOG(INFO, PMD, "Configure pmd_null: packet size is %d, "
+			"packet copy is %s\n", packet_size,
+			packet_copy ? "enabled" : "disabled");
+
+	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
+}
+
+static struct rte_driver pmd_null_drv = {
+	.name = "eth_null",
+	.type = PMD_VDEV,
+	.init = rte_pmd_null_devinit,
+};
+
+PMD_REGISTER_DRIVER(pmd_null_drv);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* Re: [PATCH] Fix linking errors when CONFIG_RTE_BUILD_SHARED_LIB is enabled
       [not found]   ` <1412137623-18817-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2014-10-01 10:50     ` Neil Horman
       [not found]       ` <20141001105022.GB21151-B26myB8xz7F8NnZeBjwnZQMhkBWG/bsMQH7oEaQurus@public.gmane.org>
  0 siblings, 1 reply; 60+ messages in thread
From: Neil Horman @ 2014-10-01 10:50 UTC (permalink / raw)
  To: mukawa-AlSX/UN32fvPDbFq/vQRIQ; +Cc: dev-VfR2kkLFssw

On Wed, Oct 01, 2014 at 01:27:03PM +0900, mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org wrote:
> From: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
> 
> When CONFIG_RTE_BUILD_SHARED_LIB is enabled, linking errors occured
> while compiling. It seems those errors are caused by wrong link order
> of some libraries. The patch fixes it like following.
> 
> 1. librte_eal
> 2. librte_malloc
> 3. librte_mempool
> 4. librte_ring
> 5. librte_pmd_bond
> 6. librte_kvargs
> 
I'm not sure why thats necesecary.  We add a --start-group/--end-group pair
halfway through this makefile.  If we just encompassed the entire set of
libraries in that group, order would be irrelevant.

Neil

> Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
> ---
>  mk/rte.app.mk | 16 ++++++++--------
>  1 file changed, 8 insertions(+), 8 deletions(-)
> 
> diff --git a/mk/rte.app.mk b/mk/rte.app.mk
> index 34dff2a..172ba4d 100644
> --- a/mk/rte.app.mk
> +++ b/mk/rte.app.mk
> @@ -121,10 +121,6 @@ endif
>  
>  LDLIBS += --start-group
>  
> -ifeq ($(CONFIG_RTE_LIBRTE_KVARGS),y)
> -LDLIBS += -lrte_kvargs
> -endif
> -
>  ifeq ($(CONFIG_RTE_LIBRTE_MBUF),y)
>  LDLIBS += -lrte_mbuf
>  endif
> @@ -137,6 +133,10 @@ ifeq ($(CONFIG_RTE_LIBRTE_ETHER),y)
>  LDLIBS += -lethdev
>  endif
>  
> +ifeq ($(CONFIG_RTE_LIBRTE_EAL),y)
> +LDLIBS += -lrte_eal
> +endif
> +
>  ifeq ($(CONFIG_RTE_LIBRTE_MALLOC),y)
>  LDLIBS += -lrte_malloc
>  endif
> @@ -158,10 +158,6 @@ ifeq ($(CONFIG_RTE_LIBGLOSS),y)
>  LDLIBS += -lgloss
>  endif
>  
> -ifeq ($(CONFIG_RTE_LIBRTE_EAL),y)
> -LDLIBS += -lrte_eal
> -endif
> -
>  ifeq ($(CONFIG_RTE_LIBRTE_CMDLINE),y)
>  LDLIBS += -lrte_cmdline
>  endif
> @@ -174,6 +170,10 @@ ifeq ($(CONFIG_RTE_LIBRTE_PMD_BOND),y)
>  LDLIBS += -lrte_pmd_bond
>  endif
>  
> +ifeq ($(CONFIG_RTE_LIBRTE_KVARGS),y)
> +LDLIBS += -lrte_kvargs
> +endif
> +
>  ifeq ($(CONFIG_RTE_LIBRTE_PMD_XENVIRT),y)
>  LDLIBS += -lrte_pmd_xenvirt
>  LDLIBS += -lxenstore
> -- 
> 1.9.1
> 
> 

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH] Fix linking errors when CONFIG_RTE_BUILD_SHARED_LIB is enabled
       [not found]       ` <20141001105022.GB21151-B26myB8xz7F8NnZeBjwnZQMhkBWG/bsMQH7oEaQurus@public.gmane.org>
@ 2014-10-01 11:56         ` Thomas Monjalon
  2014-10-02  2:48           ` Tetsuya Mukawa
  2014-10-02  1:43         ` Tetsuya Mukawa
  1 sibling, 1 reply; 60+ messages in thread
From: Thomas Monjalon @ 2014-10-01 11:56 UTC (permalink / raw)
  To: mukawa-AlSX/UN32fvPDbFq/vQRIQ; +Cc: dev-VfR2kkLFssw

2014-10-01 06:50, Neil Horman:
> On Wed, Oct 01, 2014 at 01:27:03PM +0900, mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org wrote:
> > When CONFIG_RTE_BUILD_SHARED_LIB is enabled, linking errors occured
> > while compiling. It seems those errors are caused by wrong link order
> > of some libraries. The patch fixes it like following.
> > 
> > 1. librte_eal
> > 2. librte_malloc
> > 3. librte_mempool
> > 4. librte_ring
> > 5. librte_pmd_bond
> > 6. librte_kvargs
> > 
> I'm not sure why thats necesecary.  We add a --start-group/--end-group pair
> halfway through this makefile.  If we just encompassed the entire set of
> libraries in that group, order would be irrelevant.

I don't see any error.
Please Tetsuya, could you describe how you test and what is the error message?

Thanks
-- 
Thomas

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH] Fix linking errors when CONFIG_RTE_BUILD_SHARED_LIB is enabled
       [not found]       ` <20141001105022.GB21151-B26myB8xz7F8NnZeBjwnZQMhkBWG/bsMQH7oEaQurus@public.gmane.org>
  2014-10-01 11:56         ` Thomas Monjalon
@ 2014-10-02  1:43         ` Tetsuya Mukawa
       [not found]           ` <542CADD8.9070402-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  1 sibling, 1 reply; 60+ messages in thread
From: Tetsuya Mukawa @ 2014-10-02  1:43 UTC (permalink / raw)
  To: Neil Horman; +Cc: dev-VfR2kkLFssw

(2014/10/01 19:50), Neil Horman wrote:
> I'm not sure why thats necesecary.  We add a --start-group/--end-group pair
> halfway through this makefile.  If we just encompassed the entire set of
> libraries in that group, order would be irrelevant.
I haven't known the options. Thanks.
Anyway, I understand I shouldn't change link order, but should check why
'--start-group/--end-group' doesn't work on my environment.
I will describe more in the email for Thomas.

Regards,
Tetsuya

> Neil
>
>> Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
>> ---
>>  mk/rte.app.mk | 16 ++++++++--------
>>  1 file changed, 8 insertions(+), 8 deletions(-)
>>
>> diff --git a/mk/rte.app.mk b/mk/rte.app.mk
>> index 34dff2a..172ba4d 100644
>> --- a/mk/rte.app.mk
>> +++ b/mk/rte.app.mk
>> @@ -121,10 +121,6 @@ endif
>>  
>>  LDLIBS += --start-group
>>  
>> -ifeq ($(CONFIG_RTE_LIBRTE_KVARGS),y)
>> -LDLIBS += -lrte_kvargs
>> -endif
>> -
>>  ifeq ($(CONFIG_RTE_LIBRTE_MBUF),y)
>>  LDLIBS += -lrte_mbuf
>>  endif
>> @@ -137,6 +133,10 @@ ifeq ($(CONFIG_RTE_LIBRTE_ETHER),y)
>>  LDLIBS += -lethdev
>>  endif
>>  
>> +ifeq ($(CONFIG_RTE_LIBRTE_EAL),y)
>> +LDLIBS += -lrte_eal
>> +endif
>> +
>>  ifeq ($(CONFIG_RTE_LIBRTE_MALLOC),y)
>>  LDLIBS += -lrte_malloc
>>  endif
>> @@ -158,10 +158,6 @@ ifeq ($(CONFIG_RTE_LIBGLOSS),y)
>>  LDLIBS += -lgloss
>>  endif
>>  
>> -ifeq ($(CONFIG_RTE_LIBRTE_EAL),y)
>> -LDLIBS += -lrte_eal
>> -endif
>> -
>>  ifeq ($(CONFIG_RTE_LIBRTE_CMDLINE),y)
>>  LDLIBS += -lrte_cmdline
>>  endif
>> @@ -174,6 +170,10 @@ ifeq ($(CONFIG_RTE_LIBRTE_PMD_BOND),y)
>>  LDLIBS += -lrte_pmd_bond
>>  endif
>>  
>> +ifeq ($(CONFIG_RTE_LIBRTE_KVARGS),y)
>> +LDLIBS += -lrte_kvargs
>> +endif
>> +
>>  ifeq ($(CONFIG_RTE_LIBRTE_PMD_XENVIRT),y)
>>  LDLIBS += -lrte_pmd_xenvirt
>>  LDLIBS += -lxenstore
>> -- 
>> 1.9.1
>>
>>

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH] Fix linking errors when CONFIG_RTE_BUILD_SHARED_LIB is enabled
       [not found]           ` <542CADD8.9070402-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2014-10-02  2:46             ` Matthew Hall
       [not found]               ` <20141002024626.GA24668-Hv3ogNYU3JfZZajBQzqCxQ@public.gmane.org>
  0 siblings, 1 reply; 60+ messages in thread
From: Matthew Hall @ 2014-10-02  2:46 UTC (permalink / raw)
  To: Tetsuya Mukawa; +Cc: dev-VfR2kkLFssw

On Thu, Oct 02, 2014 at 10:43:52AM +0900, Tetsuya Mukawa wrote:
> I haven't known the options. Thanks.
> Anyway, I understand I shouldn't change link order, but should check why
> '--start-group/--end-group' doesn't work on my environment.
> I will describe more in the email for Thomas.
> 
> Regards,
> Tetsuya

It's worth pointing out that you're likely better off using COMBINE_LIBS to 
make one big static lib rather than using a shared lib or you're facing a 
performance loss from the dynamic linking overhead.

Matthew.

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH] Fix linking errors when CONFIG_RTE_BUILD_SHARED_LIB is enabled
  2014-10-01 11:56         ` Thomas Monjalon
@ 2014-10-02  2:48           ` Tetsuya Mukawa
       [not found]             ` <542CBD05.5000507-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  0 siblings, 1 reply; 60+ messages in thread
From: Tetsuya Mukawa @ 2014-10-02  2:48 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev-VfR2kkLFssw

(2014/10/01 20:56), Thomas Monjalon wrote:
> 2014-10-01 06:50, Neil Horman:
>> On Wed, Oct 01, 2014 at 01:27:03PM +0900, mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org wrote:
>>> When CONFIG_RTE_BUILD_SHARED_LIB is enabled, linking errors occured
>>> while compiling. It seems those errors are caused by wrong link order
>>> of some libraries. The patch fixes it like following.
>>>
>>> 1. librte_eal
>>> 2. librte_malloc
>>> 3. librte_mempool
>>> 4. librte_ring
>>> 5. librte_pmd_bond
>>> 6. librte_kvargs
>>>
>> I'm not sure why thats necesecary.  We add a --start-group/--end-group pair
>> halfway through this makefile.  If we just encompassed the entire set of
>> libraries in that group, order would be irrelevant.
> I don't see any error.
> Please Tetsuya, could you describe how you test and what is the error message?
>
> Thanks
Thank you for testing.
I have confirmed '--start-group/--end-groups' is specified while
compiling, but I am still seeing the error.

Here is what I actually did.

----------------------------------------------------------------------

<< Show my environment >>
$ uname -a
Linux eris 3.13.0-29-generic #53-Ubuntu SMP Wed Jun 4 21:00:20 UTC 2014
x86_64 x86_64 x86_64 GNU/Linux
$ lsb_release -a
No LSB modules are available.
Distributor ID:    Ubuntu
Description:    Ubuntu 14.04.1 LTS
Release:    14.04
Codename:    trusty
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu
4.8.2-19ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs
--enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr
--program-suffix=-4.8 --enable-shared --enable-linker-build-id
--libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
--with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib
--enable-nls --with-sysroot=/ --enable-clocale=gnu
--enable-libstdcxx-debug --enable-libstdcxx-time=yes
--enable-gnu-unique-object --disable-libmudflap --enable-plugin
--with-system-zlib --disable-browser-plugin --enable-java-awt=gtk
--enable-gtk-cairo
--with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre
--enable-java-home
--with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64
--with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64
--with-arch-directory=amd64
--with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc
--enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64
--with-multilib-list=m32,m64,mx32 --with-tune=generic
--enable-checking=release --build=x86_64-linux-gnu
--host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)

<< Compile DPDK >>
$ git clone git://dpdk.org/dpdk
$ cd dpdk
$ vi config/common_linuxapp
CONFIG_RTE_BUILD_SHARED_LIB=y
$ T=x86_64-native-linuxapp-gcc make install V=1

.......

== Build app/test-acl
gcc -Wp,-MD,./.main.o.d.tmp -m64 -pthread -fPIC  -march=native
-DRTE_MACHINE_CPUFLAG_SSE -DRTE_MACHINE_CPUFLAG_SSE2
-DRTE_MACHINE_CPUFLAG_SSE3 -DRTE_MACHINE_CPUFLAG_SSSE3
-DRTE_MACHINE_CPUFLAG_SSE4_1 -DRTE_MACHINE_CPUFLAG_SSE4_2
-DRTE_MACHINE_CPUFLAG_AES -DRTE_MACHINE_CPUFLAG_PCLMULQDQ
-DRTE_MACHINE_CPUFLAG_AVX -DRTE_MACHINE_CPUFLAG_F16C
-DRTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2,RTE_CPUFLAG_AES,RTE_CPUFLAG_PCLMULQDQ,RTE_CPUFLAG_AVX,RTE_CPUFLAG_F16C 
-I/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include -include
/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include/rte_config.h -W
-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
-Wmissing-declarations -Wold-style-definition -Wpointer-arith
-Wcast-align -Wnested-externs -Wcast-qual -Wformat-nonliteral
-Wformat-security -Wundef -Wwrite-strings   -o main.o -c
/home/mukawa/tmp/dpdk/app/test-acl/main.c
gcc -m64 -pthread -fPIC  -march=native -DRTE_MACHINE_CPUFLAG_SSE
-DRTE_MACHINE_CPUFLAG_SSE2 -DRTE_MACHINE_CPUFLAG_SSE3
-DRTE_MACHINE_CPUFLAG_SSSE3 -DRTE_MACHINE_CPUFLAG_SSE4_1
-DRTE_MACHINE_CPUFLAG_SSE4_2 -DRTE_MACHINE_CPUFLAG_AES
-DRTE_MACHINE_CPUFLAG_PCLMULQDQ -DRTE_MACHINE_CPUFLAG_AVX
-DRTE_MACHINE_CPUFLAG_F16C
-DRTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2,RTE_CPUFLAG_AES,RTE_CPUFLAG_PCLMULQDQ,RTE_CPUFLAG_AVX,RTE_CPUFLAG_F16C 
-I/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include -include
/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include/rte_config.h -W
-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
-Wmissing-declarations -Wold-style-definition -Wpointer-arith
-Wcast-align -Wnested-externs -Wcast-qual -Wformat-nonliteral
-Wformat-security -Wundef -Wwrite-strings  -Wl,-Map=testacl.map,--cref
-o testacl main.o -Wl,-export-dynamic
-L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib 
-L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
-Wl,--whole-archive -Wl,-lrte_distributor -Wl,-lrte_kni
-Wl,-lrte_pipeline -Wl,-lrte_table -Wl,-lrte_port -Wl,-lrte_timer
-Wl,-lrte_hash -Wl,-lrte_lpm -Wl,-lrte_power -Wl,-lrte_acl
-Wl,-lrte_meter -Wl,-lrte_sched -Wl,-lm -Wl,-lrt -Wl,--start-group
-Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_ip_frag -Wl,-lethdev
-Wl,-lrte_malloc -Wl,-lrte_mempool -Wl,-lrte_ring -Wl,-lrte_eal
-Wl,-lrte_cmdline -Wl,-lrte_cfgfile -Wl,-lrte_pmd_bond -Wl,-lrt -Wl,-lm
-Wl,-lgcc_s -Wl,-ldl -Wl,--end-group -Wl,--no-whole-archive
/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
undefined reference to `rte_mempool_lookup'
/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
undefined reference to `rte_mempool_create'

<< Reproduce the issue with same options >>
$ cd x86_64-native-linuxapp-gcc/build/app/test-acl/
$ gcc -Wp,-MD,./.main.o.d.tmp -m64 -pthread -fPIC  -march=native
-DRTE_MACHINE_CPUFLAG_SSE -DRTE_MACHINE_CPUFLAG_SSE2
-DRTE_MACHINE_CPUFLAG_SSE3 -DRTE_MACHINE_CPUFLAG_SSSE3
-DRTE_MACHINE_CPUFLAG_SSE4_1 -DRTE_MACHINE_CPUFLAG_SSE4_2
-DRTE_MACHINE_CPUFLAG_AES -DRTE_MACHINE_CPUFLAG_PCLMULQDQ
-DRTE_MACHINE_CPUFLAG_AVX -DRTE_MACHINE_CPUFLAG_F16C
-DRTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2,RTE_CPUFLAG_AES,RTE_CPUFLAG_PCLMULQDQ,RTE_CPUFLAG_AVX,RTE_CPUFLAG_F16C 
-I/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include -include
/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include/rte_config.h -W
-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
-Wmissing-declarations -Wold-style-definition -Wpointer-arith
-Wcast-align -Wnested-externs -Wcast-qual -Wformat-nonliteral
-Wformat-security -Wundef -Wwrite-strings   -o main.o -c
/home/mukawa/tmp/dpdk/app/test-acl/main.c
mukawa@eris:~/tmp/dpdk/x86_64-native-linuxapp-gcc/build/app/test-acl$
gcc -m64 -pthread -fPIC  -march=native -DRTE_MACHINE_CPUFLAG_SSE
-DRTE_MACHINE_CPUFLAG_SSE2 -DRTE_MACHINE_CPUFLAG_SSE3
-DRTE_MACHINE_CPUFLAG_SSSE3 -DRTE_MACHINE_CPUFLAG_SSE4_1
-DRTE_MACHINE_CPUFLAG_SSE4_2 -DRTE_MACHINE_CPUFLAG_AES
-DRTE_MACHINE_CPUFLAG_PCLMULQDQ -DRTE_MACHINE_CPUFLAG_AVX
-DRTE_MACHINE_CPUFLAG_F16C
-DRTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2,RTE_CPUFLAG_AES,RTE_CPUFLAG_PCLMULQDQ,RTE_CPUFLAG_AVX,RTE_CPUFLAG_F16C 
-I/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include -include
/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include/rte_config.h -W
-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
-Wmissing-declarations -Wold-style-definition -Wpointer-arith
-Wcast-align -Wnested-externs -Wcast-qual -Wformat-nonliteral
-Wformat-security -Wundef -Wwrite-strings  -Wl,-Map=testacl.map,--cref
-o testacl main.o -Wl,-export-dynamic
-L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib 
-L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
-Wl,--whole-archive -Wl,-lrte_distributor -Wl,-lrte_kni
-Wl,-lrte_pipeline -Wl,-lrte_table -Wl,-lrte_port -Wl,-lrte_timer
-Wl,-lrte_hash -Wl,-lrte_lpm -Wl,-lrte_power -Wl,-lrte_acl
-Wl,-lrte_meter -Wl,-lrte_sched -Wl,-lm -Wl,-lrt -Wl,--start-group
-Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_ip_frag -Wl,-lethdev
-Wl,-lrte_malloc -Wl,-lrte_mempool -Wl,-lrte_ring -Wl,-lrte_eal
-Wl,-lrte_cmdline -Wl,-lrte_cfgfile -Wl,-lrte_pmd_bond -Wl,-lrt -Wl,-lm
-Wl,-lgcc_s -Wl,-ldl -Wl,--end-group -Wl,--no-whole-archive
/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
undefined reference to `rte_mempool_lookup'
/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
undefined reference to `rte_mempool_create'
collect2: error: ld returned 1 exit status

----------------------------------------------------------------------

I just enabled the following option, then compile DPDK.
CONFIG_RTE_BUILD_SHARED_LIB
Is this collect to compile PMDs as dynamic link libraries?

With the option, all libraries include are compiled as dynamic link library.
Does "--start-group/--end-group" options work with dynamic link libraries?

Regards,
Tetsuya

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH] Fix linking errors when CONFIG_RTE_BUILD_SHARED_LIB is enabled
       [not found]               ` <20141002024626.GA24668-Hv3ogNYU3JfZZajBQzqCxQ@public.gmane.org>
@ 2014-10-02  3:44                 ` Tetsuya Mukawa
  0 siblings, 0 replies; 60+ messages in thread
From: Tetsuya Mukawa @ 2014-10-02  3:44 UTC (permalink / raw)
  To: Matthew Hall; +Cc: dev-VfR2kkLFssw

(2014/10/02 11:46), Matthew Hall wrote:
> On Thu, Oct 02, 2014 at 10:43:52AM +0900, Tetsuya Mukawa wrote:
> It's worth pointing out that you're likely better off using
> COMBINE_LIBS to make one big static lib rather than using a shared lib
> or you're facing a performance loss from the dynamic linking overhead.
> Matthew. 

Thanks.  I will go over it

Regards,
Tetsuya

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH] Fix linking errors when CONFIG_RTE_BUILD_SHARED_LIB is enabled
       [not found]             ` <542CBD05.5000507-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2014-10-02  8:12               ` Sergio Gonzalez Monroy
       [not found]                 ` <20141002081221.GA27208-IWE99D/oH1/+pXziaqXtF9h3ngVCH38I@public.gmane.org>
  0 siblings, 1 reply; 60+ messages in thread
From: Sergio Gonzalez Monroy @ 2014-10-02  8:12 UTC (permalink / raw)
  To: Tetsuya Mukawa; +Cc: dev-VfR2kkLFssw

On Thu, Oct 02, 2014 at 11:48:37AM +0900, Tetsuya Mukawa wrote:
> (2014/10/01 20:56), Thomas Monjalon wrote:
> > 2014-10-01 06:50, Neil Horman:
> >> On Wed, Oct 01, 2014 at 01:27:03PM +0900, mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org wrote:
> >>> When CONFIG_RTE_BUILD_SHARED_LIB is enabled, linking errors occured
> >>> while compiling. It seems those errors are caused by wrong link order
> >>> of some libraries. The patch fixes it like following.
> >>>
> >>> 1. librte_eal
> >>> 2. librte_malloc
> >>> 3. librte_mempool
> >>> 4. librte_ring
> >>> 5. librte_pmd_bond
> >>> 6. librte_kvargs
> >>>
> >> I'm not sure why thats necesecary.  We add a --start-group/--end-group pair
> >> halfway through this makefile.  If we just encompassed the entire set of
> >> libraries in that group, order would be irrelevant.
> > I don't see any error.
> > Please Tetsuya, could you describe how you test and what is the error message?
> >
> > Thanks
> Thank you for testing.
> I have confirmed '--start-group/--end-groups' is specified while
> compiling, but I am still seeing the error.
> 
> Here is what I actually did.
> 
> ----------------------------------------------------------------------
> 
> << Show my environment >>
> $ uname -a
> Linux eris 3.13.0-29-generic #53-Ubuntu SMP Wed Jun 4 21:00:20 UTC 2014
> x86_64 x86_64 x86_64 GNU/Linux
> $ lsb_release -a
> No LSB modules are available.
> Distributor ID:    Ubuntu
> Description:    Ubuntu 14.04.1 LTS
> Release:    14.04
> Codename:    trusty
> $ gcc -v
> Using built-in specs.
> COLLECT_GCC=gcc
> COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
> Target: x86_64-linux-gnu
> Configured with: ../src/configure -v --with-pkgversion='Ubuntu
> 4.8.2-19ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs
> --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr
> --program-suffix=-4.8 --enable-shared --enable-linker-build-id
> --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
> --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib
> --enable-nls --with-sysroot=/ --enable-clocale=gnu
> --enable-libstdcxx-debug --enable-libstdcxx-time=yes
> --enable-gnu-unique-object --disable-libmudflap --enable-plugin
> --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk
> --enable-gtk-cairo
> --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre
> --enable-java-home
> --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64
> --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64
> --with-arch-directory=amd64
> --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc
> --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64
> --with-multilib-list=m32,m64,mx32 --with-tune=generic
> --enable-checking=release --build=x86_64-linux-gnu
> --host=x86_64-linux-gnu --target=x86_64-linux-gnu
> Thread model: posix
> gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)
> 
> << Compile DPDK >>
> $ git clone git://dpdk.org/dpdk
> $ cd dpdk
> $ vi config/common_linuxapp
> CONFIG_RTE_BUILD_SHARED_LIB=y
> $ T=x86_64-native-linuxapp-gcc make install V=1
> 
> .......
> 
> == Build app/test-acl
> gcc -Wp,-MD,./.main.o.d.tmp -m64 -pthread -fPIC  -march=native
> -DRTE_MACHINE_CPUFLAG_SSE -DRTE_MACHINE_CPUFLAG_SSE2
> -DRTE_MACHINE_CPUFLAG_SSE3 -DRTE_MACHINE_CPUFLAG_SSSE3
> -DRTE_MACHINE_CPUFLAG_SSE4_1 -DRTE_MACHINE_CPUFLAG_SSE4_2
> -DRTE_MACHINE_CPUFLAG_AES -DRTE_MACHINE_CPUFLAG_PCLMULQDQ
> -DRTE_MACHINE_CPUFLAG_AVX -DRTE_MACHINE_CPUFLAG_F16C
> -DRTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2,RTE_CPUFLAG_AES,RTE_CPUFLAG_PCLMULQDQ,RTE_CPUFLAG_AVX,RTE_CPUFLAG_F16C 
> -I/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include -include
> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include/rte_config.h -W
> -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
> -Wmissing-declarations -Wold-style-definition -Wpointer-arith
> -Wcast-align -Wnested-externs -Wcast-qual -Wformat-nonliteral
> -Wformat-security -Wundef -Wwrite-strings   -o main.o -c
> /home/mukawa/tmp/dpdk/app/test-acl/main.c
> gcc -m64 -pthread -fPIC  -march=native -DRTE_MACHINE_CPUFLAG_SSE
> -DRTE_MACHINE_CPUFLAG_SSE2 -DRTE_MACHINE_CPUFLAG_SSE3
> -DRTE_MACHINE_CPUFLAG_SSSE3 -DRTE_MACHINE_CPUFLAG_SSE4_1
> -DRTE_MACHINE_CPUFLAG_SSE4_2 -DRTE_MACHINE_CPUFLAG_AES
> -DRTE_MACHINE_CPUFLAG_PCLMULQDQ -DRTE_MACHINE_CPUFLAG_AVX
> -DRTE_MACHINE_CPUFLAG_F16C
> -DRTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2,RTE_CPUFLAG_AES,RTE_CPUFLAG_PCLMULQDQ,RTE_CPUFLAG_AVX,RTE_CPUFLAG_F16C 
> -I/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include -include
> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include/rte_config.h -W
> -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
> -Wmissing-declarations -Wold-style-definition -Wpointer-arith
> -Wcast-align -Wnested-externs -Wcast-qual -Wformat-nonliteral
> -Wformat-security -Wundef -Wwrite-strings  -Wl,-Map=testacl.map,--cref
> -o testacl main.o -Wl,-export-dynamic
> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib 
> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
> -Wl,--whole-archive -Wl,-lrte_distributor -Wl,-lrte_kni
> -Wl,-lrte_pipeline -Wl,-lrte_table -Wl,-lrte_port -Wl,-lrte_timer
> -Wl,-lrte_hash -Wl,-lrte_lpm -Wl,-lrte_power -Wl,-lrte_acl
> -Wl,-lrte_meter -Wl,-lrte_sched -Wl,-lm -Wl,-lrt -Wl,--start-group
> -Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_ip_frag -Wl,-lethdev
> -Wl,-lrte_malloc -Wl,-lrte_mempool -Wl,-lrte_ring -Wl,-lrte_eal
> -Wl,-lrte_cmdline -Wl,-lrte_cfgfile -Wl,-lrte_pmd_bond -Wl,-lrt -Wl,-lm
> -Wl,-lgcc_s -Wl,-ldl -Wl,--end-group -Wl,--no-whole-archive
> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
> undefined reference to `rte_mempool_lookup'
> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
> undefined reference to `rte_mempool_create'
> 
> << Reproduce the issue with same options >>
> $ cd x86_64-native-linuxapp-gcc/build/app/test-acl/
> $ gcc -Wp,-MD,./.main.o.d.tmp -m64 -pthread -fPIC  -march=native
> -DRTE_MACHINE_CPUFLAG_SSE -DRTE_MACHINE_CPUFLAG_SSE2
> -DRTE_MACHINE_CPUFLAG_SSE3 -DRTE_MACHINE_CPUFLAG_SSSE3
> -DRTE_MACHINE_CPUFLAG_SSE4_1 -DRTE_MACHINE_CPUFLAG_SSE4_2
> -DRTE_MACHINE_CPUFLAG_AES -DRTE_MACHINE_CPUFLAG_PCLMULQDQ
> -DRTE_MACHINE_CPUFLAG_AVX -DRTE_MACHINE_CPUFLAG_F16C
> -DRTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2,RTE_CPUFLAG_AES,RTE_CPUFLAG_PCLMULQDQ,RTE_CPUFLAG_AVX,RTE_CPUFLAG_F16C 
> -I/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include -include
> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include/rte_config.h -W
> -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
> -Wmissing-declarations -Wold-style-definition -Wpointer-arith
> -Wcast-align -Wnested-externs -Wcast-qual -Wformat-nonliteral
> -Wformat-security -Wundef -Wwrite-strings   -o main.o -c
> /home/mukawa/tmp/dpdk/app/test-acl/main.c
> mukawa@eris:~/tmp/dpdk/x86_64-native-linuxapp-gcc/build/app/test-acl$
> gcc -m64 -pthread -fPIC  -march=native -DRTE_MACHINE_CPUFLAG_SSE
> -DRTE_MACHINE_CPUFLAG_SSE2 -DRTE_MACHINE_CPUFLAG_SSE3
> -DRTE_MACHINE_CPUFLAG_SSSE3 -DRTE_MACHINE_CPUFLAG_SSE4_1
> -DRTE_MACHINE_CPUFLAG_SSE4_2 -DRTE_MACHINE_CPUFLAG_AES
> -DRTE_MACHINE_CPUFLAG_PCLMULQDQ -DRTE_MACHINE_CPUFLAG_AVX
> -DRTE_MACHINE_CPUFLAG_F16C
> -DRTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2,RTE_CPUFLAG_AES,RTE_CPUFLAG_PCLMULQDQ,RTE_CPUFLAG_AVX,RTE_CPUFLAG_F16C 
> -I/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include -include
> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include/rte_config.h -W
> -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
> -Wmissing-declarations -Wold-style-definition -Wpointer-arith
> -Wcast-align -Wnested-externs -Wcast-qual -Wformat-nonliteral
> -Wformat-security -Wundef -Wwrite-strings  -Wl,-Map=testacl.map,--cref
> -o testacl main.o -Wl,-export-dynamic
> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib 
> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
> -Wl,--whole-archive -Wl,-lrte_distributor -Wl,-lrte_kni
> -Wl,-lrte_pipeline -Wl,-lrte_table -Wl,-lrte_port -Wl,-lrte_timer
> -Wl,-lrte_hash -Wl,-lrte_lpm -Wl,-lrte_power -Wl,-lrte_acl
> -Wl,-lrte_meter -Wl,-lrte_sched -Wl,-lm -Wl,-lrt -Wl,--start-group
> -Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_ip_frag -Wl,-lethdev
> -Wl,-lrte_malloc -Wl,-lrte_mempool -Wl,-lrte_ring -Wl,-lrte_eal
> -Wl,-lrte_cmdline -Wl,-lrte_cfgfile -Wl,-lrte_pmd_bond -Wl,-lrt -Wl,-lm
> -Wl,-lgcc_s -Wl,-ldl -Wl,--end-group -Wl,--no-whole-archive
> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
> undefined reference to `rte_mempool_lookup'
> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
> undefined reference to `rte_mempool_create'
> collect2: error: ld returned 1 exit status
> 

Hi Tetsuya,

Would you mind posting the output of the last command adding the option '-v'?

Sergio


> ----------------------------------------------------------------------
> 
> I just enabled the following option, then compile DPDK.
> CONFIG_RTE_BUILD_SHARED_LIB
> Is this collect to compile PMDs as dynamic link libraries?
> 
> With the option, all libraries include are compiled as dynamic link library.
> Does "--start-group/--end-group" options work with dynamic link libraries?
> 
> Regards,
> Tetsuya
> 

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH] Fix linking errors when CONFIG_RTE_BUILD_SHARED_LIB is enabled
       [not found]                 ` <20141002081221.GA27208-IWE99D/oH1/+pXziaqXtF9h3ngVCH38I@public.gmane.org>
@ 2014-10-02  8:28                   ` Tetsuya Mukawa
       [not found]                     ` <542D0C94.70209-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  0 siblings, 1 reply; 60+ messages in thread
From: Tetsuya Mukawa @ 2014-10-02  8:28 UTC (permalink / raw)
  To: Sergio Gonzalez Monroy; +Cc: dev-VfR2kkLFssw

(2014/10/02 17:12), Sergio Gonzalez Monroy wrote:
> On Thu, Oct 02, 2014 at 11:48:37AM +0900, Tetsuya Mukawa wrote:
>
>> $ gcc -m64 -pthread -fPIC -march=native -DRTE_MACHINE_CPUFLAG_SSE
>> -DRTE_MACHINE_CPUFLAG_SSE2 -DRTE_MACHINE_CPUFLAG_SSE3
>> -DRTE_MACHINE_CPUFLAG_SSSE3 -DRTE_MACHINE_CPUFLAG_SSE4_1
>> -DRTE_MACHINE_CPUFLAG_SSE4_2 -DRTE_MACHINE_CPUFLAG_AES
>> -DRTE_MACHINE_CPUFLAG_PCLMULQDQ -DRTE_MACHINE_CPUFLAG_AVX
>> -DRTE_MACHINE_CPUFLAG_F16C
>> -DRTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2,RTE_CPUFLAG_AES,RTE_CPUFLAG_PCLMULQDQ,RTE_CPUFLAG_AVX,RTE_CPUFLAG_F16C
>> -I/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include -include
>> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include/rte_config.h
>> -W -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
>> -Wmissing-declarations -Wold-style-definition -Wpointer-arith
>> -Wcast-align -Wnested-externs -Wcast-qual -Wformat-nonliteral
>> -Wformat-security -Wundef -Wwrite-strings -Wl,-Map=testacl.map,--cref
>> -o testacl main.o -Wl,-export-dynamic
>> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
>> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
>> -Wl,--whole-archive -Wl,-lrte_distributor -Wl,-lrte_kni
>> -Wl,-lrte_pipeline -Wl,-lrte_table -Wl,-lrte_port -Wl,-lrte_timer
>> -Wl,-lrte_hash -Wl,-lrte_lpm -Wl,-lrte_power -Wl,-lrte_acl
>> -Wl,-lrte_meter -Wl,-lrte_sched -Wl,-lm -Wl,-lrt -Wl,--start-group
>> -Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_ip_frag -Wl,-lethdev
>> -Wl,-lrte_malloc -Wl,-lrte_mempool -Wl,-lrte_ring -Wl,-lrte_eal
>> -Wl,-lrte_cmdline -Wl,-lrte_cfgfile -Wl,-lrte_pmd_bond -Wl,-lrt
>> -Wl,-lm -Wl,-lgcc_s -Wl,-ldl -Wl,--end-group -Wl,--no-whole-archive
>> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
>> undefined reference to `rte_mempool_lookup'
>> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
>> undefined reference to `rte_mempool_create' collect2: error: ld
>> returned 1 exit status 
> Hi Tetsuya,
>
> Would you mind posting the output of the last command adding the option '-v'?
Sure, here is.

$ gcc -m64 -pthread -fPIC  -march=native -DRTE_MACHINE_CPUFLAG_SSE
-DRTE_MACHINE_CPUFLAG_SSE2 -DRTE_MACHINE_CPUFLAG_SSE3
-DRTE_MACHINE_CPUFLAG_SSSE3 -DRTE_MACHINE_CPUFLAG_SSE4_1
-DRTE_MACHINE_CPUFLAG_SSE4_2 -DRTE_MACHINE_CPUFLAG_AES
-DRTE_MACHINE_CPUFLAG_PCLMULQDQ -DRTE_MACHINE_CPUFLAG_AVX
-DRTE_MACHINE_CPUFLAG_F16C
-DRTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2,RTE_CPUFLAG_AES,RTE_CPUFLAG_PCLMULQDQ,RTE_CPUFLAG_AVX,RTE_CPUFLAG_F16C 
-I/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include -include
/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include/rte_config.h -W
-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
-Wmissing-declarations -Wold-style-definition -Wpointer-arith
-Wcast-align -Wnested-externs -Wcast-qual -Wformat-nonliteral
-Wformat-security -Wundef -Wwrite-strings  -Wl,-Map=testacl.map,--cref
-o testacl main.o -Wl,-export-dynamic
-L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib 
-L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
-Wl,--whole-archive -Wl,-lrte_distributor -Wl,-lrte_kni
-Wl,-lrte_pipeline -Wl,-lrte_table -Wl,-lrte_port -Wl,-lrte_timer
-Wl,-lrte_hash -Wl,-lrte_lpm -Wl,-lrte_power -Wl,-lrte_acl
-Wl,-lrte_meter -Wl,-lrte_sched -Wl,-lm -Wl,-lrt -Wl,--start-group
-Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_ip_frag -Wl,-lethdev
-Wl,-lrte_malloc -Wl,-lrte_mempool -Wl,-lrte_ring -Wl,-lrte_eal
-Wl,-lrte_cmdline -Wl,-lrte_cfgfile -Wl,-lrte_pmd_bond -Wl,-lrt -Wl,-lm
-Wl,-lgcc_s -Wl,-ldl -Wl,--end-group -Wl,--no-whole-archive -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu
4.8.2-19ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs
--enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr
--program-suffix=-4.8 --enable-shared --enable-linker-build-id
--libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
--with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib
--enable-nls --with-sysroot=/ --enable-clocale=gnu
--enable-libstdcxx-debug --enable-libstdcxx-time=yes
--enable-gnu-unique-object --disable-libmudflap --enable-plugin
--with-system-zlib --disable-browser-plugin --enable-java-awt=gtk
--enable-gtk-cairo
--with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre
--enable-java-home
--with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64
--with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64
--with-arch-directory=amd64
--with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc
--enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64
--with-multilib-list=m32,m64,mx32 --with-tune=generic
--enable-checking=release --build=x86_64-linux-gnu
--host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)
COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-m64' '-pthread' '-fPIC' '-march=native' '-D'
'RTE_MACHINE_CPUFLAG_SSE' '-D' 'RTE_MACHINE_CPUFLAG_SSE2' '-D'
'RTE_MACHINE_CPUFLAG_SSE3' '-D' 'RTE_MACHINE_CPUFLAG_SSSE3' '-D'
'RTE_MACHINE_CPUFLAG_SSE4_1' '-D' 'RTE_MACHINE_CPUFLAG_SSE4_2' '-D'
'RTE_MACHINE_CPUFLAG_AES' '-D' 'RTE_MACHINE_CPUFLAG_PCLMULQDQ' '-D'
'RTE_MACHINE_CPUFLAG_AVX' '-D' 'RTE_MACHINE_CPUFLAG_F16C' '-D'
'RTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2,RTE_CPUFLAG_AES,RTE_CPUFLAG_PCLMULQDQ,RTE_CPUFLAG_AVX,RTE_CPUFLAG_F16C'
'-I' '/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include'
'-include'
'/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include/rte_config.h'
'-Wextra' '-Wall' '-Werror' '-Wstrict-prototypes' '-Wmissing-prototypes'
'-Wmissing-declarations' '-Wold-style-definition' '-Wpointer-arith'
'-Wcast-align' '-Wnested-externs' '-Wcast-qual' '-Wformat-nonliteral'
'-Wformat-security' '-Wundef' '-Wwrite-strings' '-o' 'testacl'
'-L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib'
'-L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib' '-v'
 /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id
--eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed
-dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o testacl
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o
/usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o
-L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
-L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
-L/usr/lib/gcc/x86_64-linux-gnu/4.8
-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu
-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib
-L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu
-L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..
-Map=testacl.map --cref main.o -export-dynamic --whole-archive
-lrte_distributor -lrte_kni -lrte_pipeline -lrte_table -lrte_port
-lrte_timer -lrte_hash -lrte_lpm -lrte_power -lrte_acl -lrte_meter
-lrte_sched -lm -lrt --start-group -lrte_kvargs -lrte_mbuf -lrte_ip_frag
-lethdev -lrte_malloc -lrte_mempool -lrte_ring -lrte_eal -lrte_cmdline
-lrte_cfgfile -lrte_pmd_bond -lrt -lm -lgcc_s -ldl --end-group
--no-whole-archive -lgcc --as-needed -lgcc_s --no-as-needed -lpthread
-lc -lgcc --as-needed -lgcc_s --no-as-needed
/usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o
/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
undefined reference to `rte_mempool_lookup'
/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
undefined reference to `rte_mempool_create'
collect2: error: ld returned 1 exit status

Regards,
Tetsuya

> Sergio
>
>
>> ----------------------------------------------------------------------
>>
>> I just enabled the following option, then compile DPDK.
>> CONFIG_RTE_BUILD_SHARED_LIB
>> Is this collect to compile PMDs as dynamic link libraries?
>>
>> With the option, all libraries include are compiled as dynamic link library.
>> Does "--start-group/--end-group" options work with dynamic link libraries?
>>
>> Regards,
>> Tetsuya
>>

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH] Fix linking errors when CONFIG_RTE_BUILD_SHARED_LIB is enabled
       [not found]                     ` <542D0C94.70209-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2014-10-02  8:53                       ` Sergio Gonzalez Monroy
       [not found]                         ` <20141002085321.GA31287-IWE99D/oH1/+pXziaqXtF9h3ngVCH38I@public.gmane.org>
  0 siblings, 1 reply; 60+ messages in thread
From: Sergio Gonzalez Monroy @ 2014-10-02  8:53 UTC (permalink / raw)
  To: Tetsuya Mukawa; +Cc: dev-VfR2kkLFssw

On Thu, Oct 02, 2014 at 05:28:04PM +0900, Tetsuya Mukawa wrote:
> (2014/10/02 17:12), Sergio Gonzalez Monroy wrote:
> > On Thu, Oct 02, 2014 at 11:48:37AM +0900, Tetsuya Mukawa wrote:
> >
> >> $ gcc -m64 -pthread -fPIC -march=native -DRTE_MACHINE_CPUFLAG_SSE
> >> -DRTE_MACHINE_CPUFLAG_SSE2 -DRTE_MACHINE_CPUFLAG_SSE3
> >> -DRTE_MACHINE_CPUFLAG_SSSE3 -DRTE_MACHINE_CPUFLAG_SSE4_1
> >> -DRTE_MACHINE_CPUFLAG_SSE4_2 -DRTE_MACHINE_CPUFLAG_AES
> >> -DRTE_MACHINE_CPUFLAG_PCLMULQDQ -DRTE_MACHINE_CPUFLAG_AVX
> >> -DRTE_MACHINE_CPUFLAG_F16C
> >> -DRTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2,RTE_CPUFLAG_AES,RTE_CPUFLAG_PCLMULQDQ,RTE_CPUFLAG_AVX,RTE_CPUFLAG_F16C
> >> -I/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include -include
> >> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include/rte_config.h
> >> -W -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
> >> -Wmissing-declarations -Wold-style-definition -Wpointer-arith
> >> -Wcast-align -Wnested-externs -Wcast-qual -Wformat-nonliteral
> >> -Wformat-security -Wundef -Wwrite-strings -Wl,-Map=testacl.map,--cref
> >> -o testacl main.o -Wl,-export-dynamic
> >> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
> >> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
> >> -Wl,--whole-archive -Wl,-lrte_distributor -Wl,-lrte_kni
> >> -Wl,-lrte_pipeline -Wl,-lrte_table -Wl,-lrte_port -Wl,-lrte_timer
> >> -Wl,-lrte_hash -Wl,-lrte_lpm -Wl,-lrte_power -Wl,-lrte_acl
> >> -Wl,-lrte_meter -Wl,-lrte_sched -Wl,-lm -Wl,-lrt -Wl,--start-group
> >> -Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_ip_frag -Wl,-lethdev
> >> -Wl,-lrte_malloc -Wl,-lrte_mempool -Wl,-lrte_ring -Wl,-lrte_eal
> >> -Wl,-lrte_cmdline -Wl,-lrte_cfgfile -Wl,-lrte_pmd_bond -Wl,-lrt
> >> -Wl,-lm -Wl,-lgcc_s -Wl,-ldl -Wl,--end-group -Wl,--no-whole-archive
> >> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
> >> undefined reference to `rte_mempool_lookup'
> >> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
> >> undefined reference to `rte_mempool_create' collect2: error: ld
> >> returned 1 exit status 
> > Hi Tetsuya,
> >
> > Would you mind posting the output of the last command adding the option '-v'?
> Sure, here is.
> 
> $ gcc -m64 -pthread -fPIC  -march=native -DRTE_MACHINE_CPUFLAG_SSE
> -DRTE_MACHINE_CPUFLAG_SSE2 -DRTE_MACHINE_CPUFLAG_SSE3
> -DRTE_MACHINE_CPUFLAG_SSSE3 -DRTE_MACHINE_CPUFLAG_SSE4_1
> -DRTE_MACHINE_CPUFLAG_SSE4_2 -DRTE_MACHINE_CPUFLAG_AES
> -DRTE_MACHINE_CPUFLAG_PCLMULQDQ -DRTE_MACHINE_CPUFLAG_AVX
> -DRTE_MACHINE_CPUFLAG_F16C
> -DRTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2,RTE_CPUFLAG_AES,RTE_CPUFLAG_PCLMULQDQ,RTE_CPUFLAG_AVX,RTE_CPUFLAG_F16C 
> -I/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include -include
> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include/rte_config.h -W
> -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
> -Wmissing-declarations -Wold-style-definition -Wpointer-arith
> -Wcast-align -Wnested-externs -Wcast-qual -Wformat-nonliteral
> -Wformat-security -Wundef -Wwrite-strings  -Wl,-Map=testacl.map,--cref
> -o testacl main.o -Wl,-export-dynamic
> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib 
> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
> -Wl,--whole-archive -Wl,-lrte_distributor -Wl,-lrte_kni
> -Wl,-lrte_pipeline -Wl,-lrte_table -Wl,-lrte_port -Wl,-lrte_timer
> -Wl,-lrte_hash -Wl,-lrte_lpm -Wl,-lrte_power -Wl,-lrte_acl
> -Wl,-lrte_meter -Wl,-lrte_sched -Wl,-lm -Wl,-lrt -Wl,--start-group
> -Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_ip_frag -Wl,-lethdev
> -Wl,-lrte_malloc -Wl,-lrte_mempool -Wl,-lrte_ring -Wl,-lrte_eal
> -Wl,-lrte_cmdline -Wl,-lrte_cfgfile -Wl,-lrte_pmd_bond -Wl,-lrt -Wl,-lm
> -Wl,-lgcc_s -Wl,-ldl -Wl,--end-group -Wl,--no-whole-archive -v
> Using built-in specs.
> COLLECT_GCC=gcc
> COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
> Target: x86_64-linux-gnu
> Configured with: ../src/configure -v --with-pkgversion='Ubuntu
> 4.8.2-19ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs
> --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr
> --program-suffix=-4.8 --enable-shared --enable-linker-build-id
> --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
> --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib
> --enable-nls --with-sysroot=/ --enable-clocale=gnu
> --enable-libstdcxx-debug --enable-libstdcxx-time=yes
> --enable-gnu-unique-object --disable-libmudflap --enable-plugin
> --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk
> --enable-gtk-cairo
> --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre
> --enable-java-home
> --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64
> --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64
> --with-arch-directory=amd64
> --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc
> --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64
> --with-multilib-list=m32,m64,mx32 --with-tune=generic
> --enable-checking=release --build=x86_64-linux-gnu
> --host=x86_64-linux-gnu --target=x86_64-linux-gnu
> Thread model: posix
> gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)
> COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/
> LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/
> COLLECT_GCC_OPTIONS='-m64' '-pthread' '-fPIC' '-march=native' '-D'
> 'RTE_MACHINE_CPUFLAG_SSE' '-D' 'RTE_MACHINE_CPUFLAG_SSE2' '-D'
> 'RTE_MACHINE_CPUFLAG_SSE3' '-D' 'RTE_MACHINE_CPUFLAG_SSSE3' '-D'
> 'RTE_MACHINE_CPUFLAG_SSE4_1' '-D' 'RTE_MACHINE_CPUFLAG_SSE4_2' '-D'
> 'RTE_MACHINE_CPUFLAG_AES' '-D' 'RTE_MACHINE_CPUFLAG_PCLMULQDQ' '-D'
> 'RTE_MACHINE_CPUFLAG_AVX' '-D' 'RTE_MACHINE_CPUFLAG_F16C' '-D'
> 'RTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2,RTE_CPUFLAG_AES,RTE_CPUFLAG_PCLMULQDQ,RTE_CPUFLAG_AVX,RTE_CPUFLAG_F16C'
> '-I' '/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include'
> '-include'
> '/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include/rte_config.h'
> '-Wextra' '-Wall' '-Werror' '-Wstrict-prototypes' '-Wmissing-prototypes'
> '-Wmissing-declarations' '-Wold-style-definition' '-Wpointer-arith'
> '-Wcast-align' '-Wnested-externs' '-Wcast-qual' '-Wformat-nonliteral'
> '-Wformat-security' '-Wundef' '-Wwrite-strings' '-o' 'testacl'
> '-L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib'
> '-L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib' '-v'

We have been looking at this issue over the last couple of days.
It seems to be an Ubuntu GCC related bug as it works on other distros.
GCC is passing incorrectly the option '--as-needed' to LD resulting in wrong linking.

>  /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id
> --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed

The '--as-needed' just at the end of the above line is incorrect and not matching
a closing '--no-as-needed'.
You may get away with it by adding 'EXTRA_LDFLAGS=--no-as-needed'. 
ie. $ make install T=x86_64-native-linuxapp-gcc EXTRA_LDFLAGS=--no-as-needed

Sergio

> -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o testacl
> /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o
> /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o
> /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o
> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
> -L/usr/lib/gcc/x86_64-linux-gnu/4.8
> -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu
> -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib
> -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu
> -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..
> -Map=testacl.map --cref main.o -export-dynamic --whole-archive
> -lrte_distributor -lrte_kni -lrte_pipeline -lrte_table -lrte_port
> -lrte_timer -lrte_hash -lrte_lpm -lrte_power -lrte_acl -lrte_meter
> -lrte_sched -lm -lrt --start-group -lrte_kvargs -lrte_mbuf -lrte_ip_frag
> -lethdev -lrte_malloc -lrte_mempool -lrte_ring -lrte_eal -lrte_cmdline
> -lrte_cfgfile -lrte_pmd_bond -lrt -lm -lgcc_s -ldl --end-group
> --no-whole-archive -lgcc --as-needed -lgcc_s --no-as-needed -lpthread
> -lc -lgcc --as-needed -lgcc_s --no-as-needed
> /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o
> /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o
> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
> undefined reference to `rte_mempool_lookup'
> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
> undefined reference to `rte_mempool_create'
> collect2: error: ld returned 1 exit status
> 
> Regards,
> Tetsuya
> 
> > Sergio
> >
> >
> >> ----------------------------------------------------------------------
> >>
> >> I just enabled the following option, then compile DPDK.
> >> CONFIG_RTE_BUILD_SHARED_LIB
> >> Is this collect to compile PMDs as dynamic link libraries?
> >>
> >> With the option, all libraries include are compiled as dynamic link library.
> >> Does "--start-group/--end-group" options work with dynamic link libraries?
> >>
> >> Regards,
> >> Tetsuya
> >>
> 

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH] Fix linking errors when CONFIG_RTE_BUILD_SHARED_LIB is enabled
       [not found]                         ` <20141002085321.GA31287-IWE99D/oH1/+pXziaqXtF9h3ngVCH38I@public.gmane.org>
@ 2014-10-02  9:05                           ` Tetsuya Mukawa
       [not found]                             ` <542D1545.8040202-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  0 siblings, 1 reply; 60+ messages in thread
From: Tetsuya Mukawa @ 2014-10-02  9:05 UTC (permalink / raw)
  To: Sergio Gonzalez Monroy; +Cc: dev-VfR2kkLFssw

(2014/10/02 17:53), Sergio Gonzalez Monroy wrote:
> On Thu, Oct 02, 2014 at 05:28:04PM +0900, Tetsuya Mukawa wrote:
>> (2014/10/02 17:12), Sergio Gonzalez Monroy wrote:
>>> On Thu, Oct 02, 2014 at 11:48:37AM +0900, Tetsuya Mukawa wrote:
>>>
>>>> $ gcc -m64 -pthread -fPIC -march=native -DRTE_MACHINE_CPUFLAG_SSE
>>>> -DRTE_MACHINE_CPUFLAG_SSE2 -DRTE_MACHINE_CPUFLAG_SSE3
>>>> -DRTE_MACHINE_CPUFLAG_SSSE3 -DRTE_MACHINE_CPUFLAG_SSE4_1
>>>> -DRTE_MACHINE_CPUFLAG_SSE4_2 -DRTE_MACHINE_CPUFLAG_AES
>>>> -DRTE_MACHINE_CPUFLAG_PCLMULQDQ -DRTE_MACHINE_CPUFLAG_AVX
>>>> -DRTE_MACHINE_CPUFLAG_F16C
>>>> -DRTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2,RTE_CPUFLAG_AES,RTE_CPUFLAG_PCLMULQDQ,RTE_CPUFLAG_AVX,RTE_CPUFLAG_F16C
>>>> -I/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include -include
>>>> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include/rte_config.h
>>>> -W -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
>>>> -Wmissing-declarations -Wold-style-definition -Wpointer-arith
>>>> -Wcast-align -Wnested-externs -Wcast-qual -Wformat-nonliteral
>>>> -Wformat-security -Wundef -Wwrite-strings -Wl,-Map=testacl.map,--cref
>>>> -o testacl main.o -Wl,-export-dynamic
>>>> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
>>>> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
>>>> -Wl,--whole-archive -Wl,-lrte_distributor -Wl,-lrte_kni
>>>> -Wl,-lrte_pipeline -Wl,-lrte_table -Wl,-lrte_port -Wl,-lrte_timer
>>>> -Wl,-lrte_hash -Wl,-lrte_lpm -Wl,-lrte_power -Wl,-lrte_acl
>>>> -Wl,-lrte_meter -Wl,-lrte_sched -Wl,-lm -Wl,-lrt -Wl,--start-group
>>>> -Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_ip_frag -Wl,-lethdev
>>>> -Wl,-lrte_malloc -Wl,-lrte_mempool -Wl,-lrte_ring -Wl,-lrte_eal
>>>> -Wl,-lrte_cmdline -Wl,-lrte_cfgfile -Wl,-lrte_pmd_bond -Wl,-lrt
>>>> -Wl,-lm -Wl,-lgcc_s -Wl,-ldl -Wl,--end-group -Wl,--no-whole-archive
>>>> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
>>>> undefined reference to `rte_mempool_lookup'
>>>> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
>>>> undefined reference to `rte_mempool_create' collect2: error: ld
>>>> returned 1 exit status 
>>> Hi Tetsuya,
>>>
>>> Would you mind posting the output of the last command adding the option '-v'?
>> Sure, here is.
>>
>> $ gcc -m64 -pthread -fPIC  -march=native -DRTE_MACHINE_CPUFLAG_SSE
>> -DRTE_MACHINE_CPUFLAG_SSE2 -DRTE_MACHINE_CPUFLAG_SSE3
>> -DRTE_MACHINE_CPUFLAG_SSSE3 -DRTE_MACHINE_CPUFLAG_SSE4_1
>> -DRTE_MACHINE_CPUFLAG_SSE4_2 -DRTE_MACHINE_CPUFLAG_AES
>> -DRTE_MACHINE_CPUFLAG_PCLMULQDQ -DRTE_MACHINE_CPUFLAG_AVX
>> -DRTE_MACHINE_CPUFLAG_F16C
>> -DRTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2,RTE_CPUFLAG_AES,RTE_CPUFLAG_PCLMULQDQ,RTE_CPUFLAG_AVX,RTE_CPUFLAG_F16C 
>> -I/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include -include
>> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include/rte_config.h -W
>> -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
>> -Wmissing-declarations -Wold-style-definition -Wpointer-arith
>> -Wcast-align -Wnested-externs -Wcast-qual -Wformat-nonliteral
>> -Wformat-security -Wundef -Wwrite-strings  -Wl,-Map=testacl.map,--cref
>> -o testacl main.o -Wl,-export-dynamic
>> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib 
>> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
>> -Wl,--whole-archive -Wl,-lrte_distributor -Wl,-lrte_kni
>> -Wl,-lrte_pipeline -Wl,-lrte_table -Wl,-lrte_port -Wl,-lrte_timer
>> -Wl,-lrte_hash -Wl,-lrte_lpm -Wl,-lrte_power -Wl,-lrte_acl
>> -Wl,-lrte_meter -Wl,-lrte_sched -Wl,-lm -Wl,-lrt -Wl,--start-group
>> -Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_ip_frag -Wl,-lethdev
>> -Wl,-lrte_malloc -Wl,-lrte_mempool -Wl,-lrte_ring -Wl,-lrte_eal
>> -Wl,-lrte_cmdline -Wl,-lrte_cfgfile -Wl,-lrte_pmd_bond -Wl,-lrt -Wl,-lm
>> -Wl,-lgcc_s -Wl,-ldl -Wl,--end-group -Wl,--no-whole-archive -v
>> Using built-in specs.
>> COLLECT_GCC=gcc
>> COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
>> Target: x86_64-linux-gnu
>> Configured with: ../src/configure -v --with-pkgversion='Ubuntu
>> 4.8.2-19ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs
>> --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr
>> --program-suffix=-4.8 --enable-shared --enable-linker-build-id
>> --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
>> --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib
>> --enable-nls --with-sysroot=/ --enable-clocale=gnu
>> --enable-libstdcxx-debug --enable-libstdcxx-time=yes
>> --enable-gnu-unique-object --disable-libmudflap --enable-plugin
>> --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk
>> --enable-gtk-cairo
>> --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre
>> --enable-java-home
>> --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64
>> --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64
>> --with-arch-directory=amd64
>> --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc
>> --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64
>> --with-multilib-list=m32,m64,mx32 --with-tune=generic
>> --enable-checking=release --build=x86_64-linux-gnu
>> --host=x86_64-linux-gnu --target=x86_64-linux-gnu
>> Thread model: posix
>> gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)
>> COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/
>> LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/
>> COLLECT_GCC_OPTIONS='-m64' '-pthread' '-fPIC' '-march=native' '-D'
>> 'RTE_MACHINE_CPUFLAG_SSE' '-D' 'RTE_MACHINE_CPUFLAG_SSE2' '-D'
>> 'RTE_MACHINE_CPUFLAG_SSE3' '-D' 'RTE_MACHINE_CPUFLAG_SSSE3' '-D'
>> 'RTE_MACHINE_CPUFLAG_SSE4_1' '-D' 'RTE_MACHINE_CPUFLAG_SSE4_2' '-D'
>> 'RTE_MACHINE_CPUFLAG_AES' '-D' 'RTE_MACHINE_CPUFLAG_PCLMULQDQ' '-D'
>> 'RTE_MACHINE_CPUFLAG_AVX' '-D' 'RTE_MACHINE_CPUFLAG_F16C' '-D'
>> 'RTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2,RTE_CPUFLAG_AES,RTE_CPUFLAG_PCLMULQDQ,RTE_CPUFLAG_AVX,RTE_CPUFLAG_F16C'
>> '-I' '/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include'
>> '-include'
>> '/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include/rte_config.h'
>> '-Wextra' '-Wall' '-Werror' '-Wstrict-prototypes' '-Wmissing-prototypes'
>> '-Wmissing-declarations' '-Wold-style-definition' '-Wpointer-arith'
>> '-Wcast-align' '-Wnested-externs' '-Wcast-qual' '-Wformat-nonliteral'
>> '-Wformat-security' '-Wundef' '-Wwrite-strings' '-o' 'testacl'
>> '-L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib'
>> '-L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib' '-v'
> We have been looking at this issue over the last couple of days.
> It seems to be an Ubuntu GCC related bug as it works on other distros.
> GCC is passing incorrectly the option '--as-needed' to LD resulting in wrong linking.
>
>>  /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id
>> --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed
> The '--as-needed' just at the end of the above line is incorrect and not matching
> a closing '--no-as-needed'.
> You may get away with it by adding 'EXTRA_LDFLAGS=--no-as-needed'. 
> ie. $ make install T=x86_64-native-linuxapp-gcc EXTRA_LDFLAGS=--no-as-needed

I can compile DPDK with above options.
Thank you everyone for helping to solve this issue.

Regards,
Tetsuya

>
> Sergio
>
>> -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o testacl
>> /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o
>> /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o
>> /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o
>> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
>> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
>> -L/usr/lib/gcc/x86_64-linux-gnu/4.8
>> -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu
>> -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib
>> -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu
>> -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..
>> -Map=testacl.map --cref main.o -export-dynamic --whole-archive
>> -lrte_distributor -lrte_kni -lrte_pipeline -lrte_table -lrte_port
>> -lrte_timer -lrte_hash -lrte_lpm -lrte_power -lrte_acl -lrte_meter
>> -lrte_sched -lm -lrt --start-group -lrte_kvargs -lrte_mbuf -lrte_ip_frag
>> -lethdev -lrte_malloc -lrte_mempool -lrte_ring -lrte_eal -lrte_cmdline
>> -lrte_cfgfile -lrte_pmd_bond -lrt -lm -lgcc_s -ldl --end-group
>> --no-whole-archive -lgcc --as-needed -lgcc_s --no-as-needed -lpthread
>> -lc -lgcc --as-needed -lgcc_s --no-as-needed
>> /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o
>> /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o
>> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
>> undefined reference to `rte_mempool_lookup'
>> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
>> undefined reference to `rte_mempool_create'
>> collect2: error: ld returned 1 exit status
>>
>> Regards,
>> Tetsuya
>>
>>> Sergio
>>>
>>>
>>>> ----------------------------------------------------------------------
>>>>
>>>> I just enabled the following option, then compile DPDK.
>>>> CONFIG_RTE_BUILD_SHARED_LIB
>>>> Is this collect to compile PMDs as dynamic link libraries?
>>>>
>>>> With the option, all libraries include are compiled as dynamic link library.
>>>> Does "--start-group/--end-group" options work with dynamic link libraries?
>>>>
>>>> Regards,
>>>> Tetsuya
>>>>

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH] Fix linking errors when CONFIG_RTE_BUILD_SHARED_LIB is enabled
       [not found]                             ` <542D1545.8040202-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2014-10-03 11:11                               ` Sergio Gonzalez Monroy
  0 siblings, 0 replies; 60+ messages in thread
From: Sergio Gonzalez Monroy @ 2014-10-03 11:11 UTC (permalink / raw)
  To: Tetsuya Mukawa; +Cc: dev-VfR2kkLFssw

On Thu, Oct 02, 2014 at 06:05:09PM +0900, Tetsuya Mukawa wrote:
> (2014/10/02 17:53), Sergio Gonzalez Monroy wrote:
> > On Thu, Oct 02, 2014 at 05:28:04PM +0900, Tetsuya Mukawa wrote:
> >> (2014/10/02 17:12), Sergio Gonzalez Monroy wrote:
> >>> On Thu, Oct 02, 2014 at 11:48:37AM +0900, Tetsuya Mukawa wrote:
> >>>
> >>>> $ gcc -m64 -pthread -fPIC -march=native -DRTE_MACHINE_CPUFLAG_SSE
> >>>> -DRTE_MACHINE_CPUFLAG_SSE2 -DRTE_MACHINE_CPUFLAG_SSE3
> >>>> -DRTE_MACHINE_CPUFLAG_SSSE3 -DRTE_MACHINE_CPUFLAG_SSE4_1
> >>>> -DRTE_MACHINE_CPUFLAG_SSE4_2 -DRTE_MACHINE_CPUFLAG_AES
> >>>> -DRTE_MACHINE_CPUFLAG_PCLMULQDQ -DRTE_MACHINE_CPUFLAG_AVX
> >>>> -DRTE_MACHINE_CPUFLAG_F16C
> >>>> -DRTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2,RTE_CPUFLAG_AES,RTE_CPUFLAG_PCLMULQDQ,RTE_CPUFLAG_AVX,RTE_CPUFLAG_F16C
> >>>> -I/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include -include
> >>>> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include/rte_config.h
> >>>> -W -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
> >>>> -Wmissing-declarations -Wold-style-definition -Wpointer-arith
> >>>> -Wcast-align -Wnested-externs -Wcast-qual -Wformat-nonliteral
> >>>> -Wformat-security -Wundef -Wwrite-strings -Wl,-Map=testacl.map,--cref
> >>>> -o testacl main.o -Wl,-export-dynamic
> >>>> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
> >>>> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
> >>>> -Wl,--whole-archive -Wl,-lrte_distributor -Wl,-lrte_kni
> >>>> -Wl,-lrte_pipeline -Wl,-lrte_table -Wl,-lrte_port -Wl,-lrte_timer
> >>>> -Wl,-lrte_hash -Wl,-lrte_lpm -Wl,-lrte_power -Wl,-lrte_acl
> >>>> -Wl,-lrte_meter -Wl,-lrte_sched -Wl,-lm -Wl,-lrt -Wl,--start-group
> >>>> -Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_ip_frag -Wl,-lethdev
> >>>> -Wl,-lrte_malloc -Wl,-lrte_mempool -Wl,-lrte_ring -Wl,-lrte_eal
> >>>> -Wl,-lrte_cmdline -Wl,-lrte_cfgfile -Wl,-lrte_pmd_bond -Wl,-lrt
> >>>> -Wl,-lm -Wl,-lgcc_s -Wl,-ldl -Wl,--end-group -Wl,--no-whole-archive
> >>>> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
> >>>> undefined reference to `rte_mempool_lookup'
> >>>> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
> >>>> undefined reference to `rte_mempool_create' collect2: error: ld
> >>>> returned 1 exit status 
> >>> Hi Tetsuya,
> >>>
> >>> Would you mind posting the output of the last command adding the option '-v'?
> >> Sure, here is.
> >>
> >> $ gcc -m64 -pthread -fPIC  -march=native -DRTE_MACHINE_CPUFLAG_SSE
> >> -DRTE_MACHINE_CPUFLAG_SSE2 -DRTE_MACHINE_CPUFLAG_SSE3
> >> -DRTE_MACHINE_CPUFLAG_SSSE3 -DRTE_MACHINE_CPUFLAG_SSE4_1
> >> -DRTE_MACHINE_CPUFLAG_SSE4_2 -DRTE_MACHINE_CPUFLAG_AES
> >> -DRTE_MACHINE_CPUFLAG_PCLMULQDQ -DRTE_MACHINE_CPUFLAG_AVX
> >> -DRTE_MACHINE_CPUFLAG_F16C
> >> -DRTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2,RTE_CPUFLAG_AES,RTE_CPUFLAG_PCLMULQDQ,RTE_CPUFLAG_AVX,RTE_CPUFLAG_F16C 
> >> -I/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include -include
> >> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include/rte_config.h -W
> >> -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
> >> -Wmissing-declarations -Wold-style-definition -Wpointer-arith
> >> -Wcast-align -Wnested-externs -Wcast-qual -Wformat-nonliteral
> >> -Wformat-security -Wundef -Wwrite-strings  -Wl,-Map=testacl.map,--cref
> >> -o testacl main.o -Wl,-export-dynamic
> >> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib 
> >> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
> >> -Wl,--whole-archive -Wl,-lrte_distributor -Wl,-lrte_kni
> >> -Wl,-lrte_pipeline -Wl,-lrte_table -Wl,-lrte_port -Wl,-lrte_timer
> >> -Wl,-lrte_hash -Wl,-lrte_lpm -Wl,-lrte_power -Wl,-lrte_acl
> >> -Wl,-lrte_meter -Wl,-lrte_sched -Wl,-lm -Wl,-lrt -Wl,--start-group
> >> -Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_ip_frag -Wl,-lethdev
> >> -Wl,-lrte_malloc -Wl,-lrte_mempool -Wl,-lrte_ring -Wl,-lrte_eal
> >> -Wl,-lrte_cmdline -Wl,-lrte_cfgfile -Wl,-lrte_pmd_bond -Wl,-lrt -Wl,-lm
> >> -Wl,-lgcc_s -Wl,-ldl -Wl,--end-group -Wl,--no-whole-archive -v
> >> Using built-in specs.
> >> COLLECT_GCC=gcc
> >> COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
> >> Target: x86_64-linux-gnu
> >> Configured with: ../src/configure -v --with-pkgversion='Ubuntu
> >> 4.8.2-19ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs
> >> --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr
> >> --program-suffix=-4.8 --enable-shared --enable-linker-build-id
> >> --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
> >> --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib
> >> --enable-nls --with-sysroot=/ --enable-clocale=gnu
> >> --enable-libstdcxx-debug --enable-libstdcxx-time=yes
> >> --enable-gnu-unique-object --disable-libmudflap --enable-plugin
> >> --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk
> >> --enable-gtk-cairo
> >> --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre
> >> --enable-java-home
> >> --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64
> >> --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64
> >> --with-arch-directory=amd64
> >> --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc
> >> --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64
> >> --with-multilib-list=m32,m64,mx32 --with-tune=generic
> >> --enable-checking=release --build=x86_64-linux-gnu
> >> --host=x86_64-linux-gnu --target=x86_64-linux-gnu
> >> Thread model: posix
> >> gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)
> >> COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/
> >> LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/
> >> COLLECT_GCC_OPTIONS='-m64' '-pthread' '-fPIC' '-march=native' '-D'
> >> 'RTE_MACHINE_CPUFLAG_SSE' '-D' 'RTE_MACHINE_CPUFLAG_SSE2' '-D'
> >> 'RTE_MACHINE_CPUFLAG_SSE3' '-D' 'RTE_MACHINE_CPUFLAG_SSSE3' '-D'
> >> 'RTE_MACHINE_CPUFLAG_SSE4_1' '-D' 'RTE_MACHINE_CPUFLAG_SSE4_2' '-D'
> >> 'RTE_MACHINE_CPUFLAG_AES' '-D' 'RTE_MACHINE_CPUFLAG_PCLMULQDQ' '-D'
> >> 'RTE_MACHINE_CPUFLAG_AVX' '-D' 'RTE_MACHINE_CPUFLAG_F16C' '-D'
> >> 'RTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2,RTE_CPUFLAG_AES,RTE_CPUFLAG_PCLMULQDQ,RTE_CPUFLAG_AVX,RTE_CPUFLAG_F16C'
> >> '-I' '/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include'
> >> '-include'
> >> '/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/include/rte_config.h'
> >> '-Wextra' '-Wall' '-Werror' '-Wstrict-prototypes' '-Wmissing-prototypes'
> >> '-Wmissing-declarations' '-Wold-style-definition' '-Wpointer-arith'
> >> '-Wcast-align' '-Wnested-externs' '-Wcast-qual' '-Wformat-nonliteral'
> >> '-Wformat-security' '-Wundef' '-Wwrite-strings' '-o' 'testacl'
> >> '-L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib'
> >> '-L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib' '-v'
> > We have been looking at this issue over the last couple of days.
> > It seems to be an Ubuntu GCC related bug as it works on other distros.
> > GCC is passing incorrectly the option '--as-needed' to LD resulting in wrong linking.
> >

Just a quick follow up on this issue and to rectify myself. 
This is not a bug but expected behavior:
https://wiki.debian.org/ToolChain/DSOLinking#Onlylinkwithneededlibraries

Sergio

> >>  /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id
> >> --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed
> > The '--as-needed' just at the end of the above line is incorrect and not matching
> > a closing '--no-as-needed'.
> > You may get away with it by adding 'EXTRA_LDFLAGS=--no-as-needed'. 
> > ie. $ make install T=x86_64-native-linuxapp-gcc EXTRA_LDFLAGS=--no-as-needed
> 
> I can compile DPDK with above options.
> Thank you everyone for helping to solve this issue.
> 
> Regards,
> Tetsuya
> 
> >
> > Sergio
> >
> >> -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o testacl
> >> /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o
> >> /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o
> >> /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o
> >> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
> >> -L/home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib
> >> -L/usr/lib/gcc/x86_64-linux-gnu/4.8
> >> -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu
> >> -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib
> >> -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu
> >> -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..
> >> -Map=testacl.map --cref main.o -export-dynamic --whole-archive
> >> -lrte_distributor -lrte_kni -lrte_pipeline -lrte_table -lrte_port
> >> -lrte_timer -lrte_hash -lrte_lpm -lrte_power -lrte_acl -lrte_meter
> >> -lrte_sched -lm -lrt --start-group -lrte_kvargs -lrte_mbuf -lrte_ip_frag
> >> -lethdev -lrte_malloc -lrte_mempool -lrte_ring -lrte_eal -lrte_cmdline
> >> -lrte_cfgfile -lrte_pmd_bond -lrt -lm -lgcc_s -ldl --end-group
> >> --no-whole-archive -lgcc --as-needed -lgcc_s --no-as-needed -lpthread
> >> -lc -lgcc --as-needed -lgcc_s --no-as-needed
> >> /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o
> >> /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o
> >> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
> >> undefined reference to `rte_mempool_lookup'
> >> /home/mukawa/tmp/dpdk/x86_64-native-linuxapp-gcc/lib/librte_eal.so:
> >> undefined reference to `rte_mempool_create'
> >> collect2: error: ld returned 1 exit status
> >>
> >> Regards,
> >> Tetsuya
> >>
> >>> Sergio
> >>>
> >>>
> >>>> ----------------------------------------------------------------------
> >>>>
> >>>> I just enabled the following option, then compile DPDK.
> >>>> CONFIG_RTE_BUILD_SHARED_LIB
> >>>> Is this collect to compile PMDs as dynamic link libraries?
> >>>>
> >>>> With the option, all libraries include are compiled as dynamic link library.
> >>>> Does "--start-group/--end-group" options work with dynamic link libraries?
> >>>>
> >>>> Regards,
> >>>> Tetsuya
> >>>>
> 
> 

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v2] librte_pmd_null: Add null PMD
       [not found]       ` <1412139437-26749-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2014-11-13 12:17         ` Thomas Monjalon
  2014-12-16  8:39         ` [PATCH v3] " Tetsuya Mukawa
  1 sibling, 0 replies; 60+ messages in thread
From: Thomas Monjalon @ 2014-11-13 12:17 UTC (permalink / raw)
  To: dev-VfR2kkLFssw
  Cc: nakajima.yoshihiro-Zyj7fXuS5i5L9jVzuh4AOg,
	masutani.hitoshi-Zyj7fXuS5i5L9jVzuh4AOg

Hi,

2014-10-01 13:57, mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org:
> 'null PMD' is a driver of the virtual device particulary designed to measure
> performance of DPDK PMDs. When an application call rx, null PMD just allocates
> mbufs and returns those. Also tx, the PMD just frees mbufs.
> 
> The PMD has following options.
> - size: specify packe size allocated by RX. Default packet size is 64.
> - copy: specify 1 or 0 to enable or disable copy while RX and TX.
> 	Default value is 0(disbaled).
> 	This option is used for emulating more realistic data transfer.
> 	Copy size is equal to packet size.
> 
> To use the PMD, enable CONFIG_RTE_BUILD_SHARED_LIB in config file. Then
> compile the PMD as shared library. The library can be linked using '-d'
> option when an application invokes.
> 
> Here is an example.
> $ sudo ./testpmd -c f -n 4 -d librte_pmd_null.so \
> 	--vdev 'eth_null0' --vdev 'eth_null1' -- -i
> 
> If testpmd is compiled with CONFIG_RTE_BUILD_SHARED_LIB, it may need to
> specify more libraries using '-d' option.
> 
> Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>

This patch is still pending because nobody reviewed it.

-- 
Thomas

^ permalink raw reply	[flat|nested] 60+ messages in thread

* [PATCH v3] librte_pmd_null: Add null PMD
       [not found]       ` <1412139437-26749-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  2014-11-13 12:17         ` Thomas Monjalon
@ 2014-12-16  8:39         ` Tetsuya Mukawa
       [not found]           ` <1418719167-8235-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  1 sibling, 1 reply; 60+ messages in thread
From: Tetsuya Mukawa @ 2014-12-16  8:39 UTC (permalink / raw)
  To: dev-VfR2kkLFssw

'null PMD' is a driver of the virtual device particulary designed to measure
performance of DPDK PMDs. When an application call rx, null PMD just allocates
mbufs and returns those. Also tx, the PMD just frees mbufs.

The PMD has following options.
- size: specify packe size allocated by RX. Default packet size is 64.
- copy: specify 1 or 0 to enable or disable copy while RX and TX.
	Default value is 0(disbaled).
	This option is used for emulating more realistic data transfer.
	Copy size is equal to packet size.

To use the PMD, enable CONFIG_RTE_BUILD_SHARED_LIB in config file. Then
compile the PMD as shared library. The library can be linked using '-d'
option when an application invokes.

Here is an example.
$ sudo ./testpmd -c f -n 4 -d librte_pmd_null.so \
	--vdev 'eth_null0' --vdev 'eth_null1' -- -i

If testpmd is compiled with CONFIG_RTE_BUILD_SHARED_LIB, it may need to
specify more libraries using '-d' option.

Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
---
 config/common_bsdapp               |   5 +
 config/common_linuxapp             |   5 +
 lib/Makefile                       |   1 +
 lib/librte_pmd_null/Makefile       |  58 +++++
 lib/librte_pmd_null/rte_eth_null.c | 474 +++++++++++++++++++++++++++++++++++++
 5 files changed, 543 insertions(+)
 create mode 100644 lib/librte_pmd_null/Makefile
 create mode 100644 lib/librte_pmd_null/rte_eth_null.c

diff --git a/config/common_bsdapp b/config/common_bsdapp
index 9177db1..fa849be 100644
--- a/config/common_bsdapp
+++ b/config/common_bsdapp
@@ -224,6 +224,11 @@ CONFIG_RTE_LIBRTE_PMD_PCAP=y
 CONFIG_RTE_LIBRTE_PMD_BOND=y
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/config/common_linuxapp b/config/common_linuxapp
index 2f9643b..808574a 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -232,6 +232,11 @@ CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
 CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/lib/Makefile b/lib/Makefile
index 0ffc982..d246c53 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -52,6 +52,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += librte_pmd_virtio
 DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt
 DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += librte_vhost
+DIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += librte_pmd_null
 DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash
 DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm
 DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl
diff --git a/lib/librte_pmd_null/Makefile b/lib/librte_pmd_null/Makefile
new file mode 100644
index 0000000..0ec4db9
--- /dev/null
+++ b/lib/librte_pmd_null/Makefile
@@ -0,0 +1,58 @@
+#   BSD LICENSE
+#
+#   Copyright (C) IGEL Co.,Ltd.
+#   All rights reserved.
+#
+#   Redistribution and use in source and binary forms, with or without
+#   modification, are permitted provided that the following conditions
+#   are met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in
+#       the documentation and/or other materials provided with the
+#       distribution.
+#     * Neither the name of IGEL Co.,Ltd. nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_pmd_null.a
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += rte_eth_null.c
+
+#
+# Export include files
+#
+SYMLINK-y-include +=
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_malloc
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_kvargs
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
new file mode 100644
index 0000000..7ecdd17
--- /dev/null
+++ b/lib/librte_pmd_null/rte_eth_null.c
@@ -0,0 +1,474 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright (C) IGEL Co.,Ltd.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of IGEL Co.,Ltd. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_dev.h>
+#include <rte_kvargs.h>
+
+#define ETH_NULL_PACKET_SIZE_ARG	"size"
+#define ETH_NULL_PACKET_COPY_ARG	"copy"
+
+static unsigned default_packet_size = 64;
+static unsigned default_packet_copy;
+
+static const char const *valid_arguments[] = {
+	ETH_NULL_PACKET_SIZE_ARG,
+	ETH_NULL_PACKET_COPY_ARG,
+	NULL
+};
+
+struct pmd_internals;
+
+struct null_queue {
+	struct pmd_internals *internals;
+
+	struct rte_mempool *mb_pool;
+	struct rte_mbuf *dummy_packet;
+
+	rte_atomic64_t rx_pkts;
+	rte_atomic64_t tx_pkts;
+	rte_atomic64_t err_pkts;
+};
+
+struct pmd_internals {
+	unsigned packet_size;
+	unsigned packet_copy;
+	unsigned numa_node;
+
+	unsigned nb_rx_queues;
+	unsigned nb_tx_queues;
+
+	struct null_queue rx_null_queues[1];
+	struct null_queue tx_null_queues[1];
+};
+
+
+static struct ether_addr eth_addr = { .addr_bytes = {0} };
+static const char *drivername = "Null PMD";
+static struct rte_eth_link pmd_link = {
+	.link_speed = 10000,
+	.link_duplex = ETH_LINK_FULL_DUPLEX,
+	.link_status = 0
+};
+
+static uint16_t
+eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,
+					packet_size);
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_tx(void *q, struct rte_mbuf **bufs __rte_unused, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+
+	for (i = 0; i < nb_bufs; i++)
+		rte_pktmbuf_free(bufs[i]);
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	for (i = 0; i < nb_bufs; i++) {
+		rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *),
+					packet_size);
+		rte_pktmbuf_free(bufs[i]);
+	}
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static int
+eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; }
+
+static int
+eth_dev_start(struct rte_eth_dev *dev)
+{
+	dev->data->dev_link.link_status = 1;
+	return 0;
+}
+
+static void
+eth_dev_stop(struct rte_eth_dev *dev)
+{
+	dev->data->dev_link.link_status = 0;
+}
+
+static int
+eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+		uint16_t nb_rx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_rxconf *rx_conf __rte_unused,
+		struct rte_mempool *mb_pool __rte_unused)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals = dev->data->dev_private;
+	unsigned packet_size = internals->packet_size;
+
+	if (rx_queue_id != 0)
+			return -ENODEV;
+
+	internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool;
+	dev->data->rx_queues[rx_queue_id] =
+		&internals->rx_null_queues[rx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->rx_null_queues[rx_queue_id].internals = internals;
+	internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+static int
+eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+		uint16_t nb_tx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals = dev->data->dev_private;
+	unsigned packet_size = internals->packet_size;
+
+	if (tx_queue_id != 0)
+			return -ENODEV;
+
+	dev->data->tx_queues[tx_queue_id] =
+		&internals->tx_null_queues[tx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->tx_null_queues[tx_queue_id].internals = internals;
+	internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+
+static void
+eth_dev_info(struct rte_eth_dev *dev,
+		struct rte_eth_dev_info *dev_info)
+{
+	struct pmd_internals *internals = dev->data->dev_private;
+
+	dev_info->driver_name = drivername;
+	dev_info->max_mac_addrs = 1;
+	dev_info->max_rx_pktlen = (uint32_t)-1;
+	dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;
+	dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;
+	dev_info->min_rx_bufsize = 0;
+	dev_info->pci_dev = NULL;
+}
+
+static void
+eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)
+{
+	unsigned i;
+	unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
+	const struct pmd_internals *internal = dev->data->dev_private;
+
+	memset(igb_stats, 0, sizeof(*igb_stats));
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_rx_queues; i++) {
+		igb_stats->q_ipackets[i] =
+			internal->rx_null_queues[i].rx_pkts.cnt;
+		rx_total += igb_stats->q_ipackets[i];
+	}
+
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_tx_queues; i++) {
+		igb_stats->q_opackets[i] =
+			internal->tx_null_queues[i].tx_pkts.cnt;
+		igb_stats->q_errors[i] =
+			internal->tx_null_queues[i].err_pkts.cnt;
+		tx_total += igb_stats->q_opackets[i];
+		tx_err_total += igb_stats->q_errors[i];
+	}
+
+	igb_stats->ipackets = rx_total;
+	igb_stats->opackets = tx_total;
+	igb_stats->oerrors = tx_err_total;
+}
+
+static void
+eth_stats_reset(struct rte_eth_dev *dev)
+{
+	unsigned i;
+	struct pmd_internals *internal = dev->data->dev_private;
+
+	for (i = 0; i < internal->nb_rx_queues; i++)
+		internal->rx_null_queues[i].rx_pkts.cnt = 0;
+	for (i = 0; i < internal->nb_tx_queues; i++) {
+		internal->tx_null_queues[i].tx_pkts.cnt = 0;
+		internal->tx_null_queues[i].err_pkts.cnt = 0;
+	}
+}
+
+static void
+eth_queue_release(void *q __rte_unused) { ; }
+static int
+eth_link_update(struct rte_eth_dev *dev __rte_unused,
+		int wait_to_complete __rte_unused) { return 0; }
+
+static struct eth_dev_ops ops = {
+		.dev_start = eth_dev_start,
+		.dev_stop = eth_dev_stop,
+		.dev_configure = eth_dev_configure,
+		.dev_infos_get = eth_dev_info,
+		.rx_queue_setup = eth_rx_queue_setup,
+		.tx_queue_setup = eth_tx_queue_setup,
+		.rx_queue_release = eth_queue_release,
+		.tx_queue_release = eth_queue_release,
+		.link_update = eth_link_update,
+		.stats_get = eth_stats_get,
+		.stats_reset = eth_stats_reset,
+};
+
+static int
+eth_dev_null_create(const char *name __rte_unused,
+		const unsigned numa_node,
+		unsigned packet_size,
+		unsigned packet_copy)
+{
+	const unsigned nb_rx_queues = 1;
+	const unsigned nb_tx_queues = 1;
+	struct rte_eth_dev_data *data = NULL;
+	struct rte_pci_device *pci_dev = NULL;
+	struct pmd_internals *internals = NULL;
+	struct rte_eth_dev *eth_dev = NULL;
+
+	RTE_LOG(INFO, PMD, "Creating null ethdev on numa socket %u\n",
+			numa_node);
+
+	/* now do all data allocation - for eth_dev structure, dummy pci driver
+	 * and internal (private) data
+	 */
+	data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);
+	if (data == NULL)
+		goto error;
+
+	pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);
+	if (pci_dev == NULL)
+		goto error;
+
+	internals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node);
+	if (internals == NULL)
+		goto error;
+
+	/* reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocate(name);
+	if (eth_dev == NULL)
+		goto error;
+
+	/* now put it all together
+	 * - store queue data in internals,
+	 * - store numa_node info in pci_driver
+	 * - point eth_dev_data to internals and pci_driver
+	 * - and point eth_dev structure to new eth_dev_data structure
+	 */
+	/* NOTE: we'll replace the data element, of originally allocated eth_dev
+	 * so the nulls are local per-process */
+
+	internals->nb_rx_queues = nb_rx_queues;
+	internals->nb_tx_queues = nb_tx_queues;
+	internals->packet_size = packet_size;
+	internals->packet_copy = packet_copy;
+	internals->numa_node = numa_node;
+
+	pci_dev->numa_node = numa_node;
+
+	data->dev_private = internals;
+	data->port_id = eth_dev->data->port_id;
+	data->nb_rx_queues = (uint16_t)nb_rx_queues;
+	data->nb_tx_queues = (uint16_t)nb_tx_queues;
+	data->dev_link = pmd_link;
+	data->mac_addrs = &eth_addr;
+
+	eth_dev->data = data;
+	eth_dev->dev_ops = &ops;
+	eth_dev->pci_dev = pci_dev;
+
+	/* finally assign rx and tx ops */
+	if (packet_copy) {
+		eth_dev->rx_pkt_burst = eth_null_copy_rx;
+		eth_dev->tx_pkt_burst = eth_null_copy_tx;
+	} else {
+		eth_dev->rx_pkt_burst = eth_null_rx;
+		eth_dev->tx_pkt_burst = eth_null_tx;
+	}
+
+	return 0;
+
+error:
+	if (data)
+		rte_free(data);
+	if (pci_dev)
+		rte_free(pci_dev);
+	if (internals)
+		rte_free(internals);
+	return -1;
+}
+
+static inline int
+get_packet_size_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_size = extra_args;
+
+	*packet_size = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_size == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static inline int
+get_packet_copy_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_copy = extra_args;
+
+	*packet_copy = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_copy == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static int
+rte_pmd_null_devinit(const char *name, const char *params)
+{
+	unsigned numa_node;
+	unsigned packet_size = default_packet_size;
+	unsigned packet_copy = default_packet_copy;
+	struct rte_kvargs *kvlist;
+	int ret;
+
+	RTE_LOG(INFO, PMD, "Initializing pmd_null for %s\n", name);
+
+	numa_node = rte_socket_id();
+
+	kvlist = rte_kvargs_parse(params, valid_arguments);
+	if (kvlist == NULL)
+		return -1;
+
+	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) {
+
+		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_SIZE_ARG,
+				&get_packet_size_arg, &packet_size);
+		if (ret < 0)
+			return -1;
+	}
+
+	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) {
+
+		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_COPY_ARG,
+				&get_packet_copy_arg, &packet_copy);
+		if (ret < 0)
+			return -1;
+	}
+
+	RTE_LOG(INFO, PMD, "Configure pmd_null: packet size is %d, "
+			"packet copy is %s\n", packet_size,
+			packet_copy ? "enabled" : "disabled");
+
+	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
+}
+
+static struct rte_driver pmd_null_drv = {
+	.name = "eth_null",
+	.type = PMD_VDEV,
+	.init = rte_pmd_null_devinit,
+};
+
+PMD_REGISTER_DRIVER(pmd_null_drv);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* Re: [PATCH v3] librte_pmd_null: Add null PMD
       [not found]           ` <1418719167-8235-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2014-12-16  8:44             ` Tetsuya Mukawa
       [not found]               ` <548FF0EA.3010501-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  2015-01-20  3:00             ` [PATCH v4 1/2] " Tetsuya Mukawa
  1 sibling, 1 reply; 60+ messages in thread
From: Tetsuya Mukawa @ 2014-12-16  8:44 UTC (permalink / raw)
  To: dev-VfR2kkLFssw

I've updated the null PMD to apply it to latest DPDK.
Also I've sent a port hotplug patch for null PMD.

Thanks,
Tetsuya

(2014/12/16 17:39), Tetsuya Mukawa wrote:
> 'null PMD' is a driver of the virtual device particulary designed to measure
> performance of DPDK PMDs. When an application call rx, null PMD just allocates
> mbufs and returns those. Also tx, the PMD just frees mbufs.
>
> The PMD has following options.
> - size: specify packe size allocated by RX. Default packet size is 64.
> - copy: specify 1 or 0 to enable or disable copy while RX and TX.
> 	Default value is 0(disbaled).
> 	This option is used for emulating more realistic data transfer.
> 	Copy size is equal to packet size.
>
> To use the PMD, enable CONFIG_RTE_BUILD_SHARED_LIB in config file. Then
> compile the PMD as shared library. The library can be linked using '-d'
> option when an application invokes.
>
> Here is an example.
> $ sudo ./testpmd -c f -n 4 -d librte_pmd_null.so \
> 	--vdev 'eth_null0' --vdev 'eth_null1' -- -i
>
> If testpmd is compiled with CONFIG_RTE_BUILD_SHARED_LIB, it may need to
> specify more libraries using '-d' option.
>
> Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
> ---
>  config/common_bsdapp               |   5 +
>  config/common_linuxapp             |   5 +
>  lib/Makefile                       |   1 +
>  lib/librte_pmd_null/Makefile       |  58 +++++
>  lib/librte_pmd_null/rte_eth_null.c | 474 +++++++++++++++++++++++++++++++++++++
>  5 files changed, 543 insertions(+)
>  create mode 100644 lib/librte_pmd_null/Makefile
>  create mode 100644 lib/librte_pmd_null/rte_eth_null.c
>
> diff --git a/config/common_bsdapp b/config/common_bsdapp
> index 9177db1..fa849be 100644
> --- a/config/common_bsdapp
> +++ b/config/common_bsdapp
> @@ -224,6 +224,11 @@ CONFIG_RTE_LIBRTE_PMD_PCAP=y
>  CONFIG_RTE_LIBRTE_PMD_BOND=y
>  
>  #
> +# Compile null PMD
> +#
> +CONFIG_RTE_LIBRTE_PMD_NULL=y
> +
> +#
>  # Do prefetch of packet data within PMD driver receive function
>  #
>  CONFIG_RTE_PMD_PACKET_PREFETCH=y
> diff --git a/config/common_linuxapp b/config/common_linuxapp
> index 2f9643b..808574a 100644
> --- a/config/common_linuxapp
> +++ b/config/common_linuxapp
> @@ -232,6 +232,11 @@ CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
>  CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
>  
>  #
> +# Compile null PMD
> +#
> +CONFIG_RTE_LIBRTE_PMD_NULL=y
> +
> +#
>  # Do prefetch of packet data within PMD driver receive function
>  #
>  CONFIG_RTE_PMD_PACKET_PREFETCH=y
> diff --git a/lib/Makefile b/lib/Makefile
> index 0ffc982..d246c53 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -52,6 +52,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += librte_pmd_virtio
>  DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3
>  DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt
>  DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += librte_vhost
> +DIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += librte_pmd_null
>  DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash
>  DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm
>  DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl
> diff --git a/lib/librte_pmd_null/Makefile b/lib/librte_pmd_null/Makefile
> new file mode 100644
> index 0000000..0ec4db9
> --- /dev/null
> +++ b/lib/librte_pmd_null/Makefile
> @@ -0,0 +1,58 @@
> +#   BSD LICENSE
> +#
> +#   Copyright (C) IGEL Co.,Ltd.
> +#   All rights reserved.
> +#
> +#   Redistribution and use in source and binary forms, with or without
> +#   modification, are permitted provided that the following conditions
> +#   are met:
> +#
> +#     * Redistributions of source code must retain the above copyright
> +#       notice, this list of conditions and the following disclaimer.
> +#     * Redistributions in binary form must reproduce the above copyright
> +#       notice, this list of conditions and the following disclaimer in
> +#       the documentation and/or other materials provided with the
> +#       distribution.
> +#     * Neither the name of IGEL Co.,Ltd. nor the names of its
> +#       contributors may be used to endorse or promote products derived
> +#       from this software without specific prior written permission.
> +#
> +#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> +#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> +#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> +#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> +#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> +#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> +#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> +#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> +#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> +#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> +#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +
> +include $(RTE_SDK)/mk/rte.vars.mk
> +
> +#
> +# library name
> +#
> +LIB = librte_pmd_null.a
> +
> +CFLAGS += -O3
> +CFLAGS += $(WERROR_FLAGS)
> +
> +#
> +# all source are stored in SRCS-y
> +#
> +SRCS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += rte_eth_null.c
> +
> +#
> +# Export include files
> +#
> +SYMLINK-y-include +=
> +
> +# this lib depends upon:
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_mbuf
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_ether
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_malloc
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_kvargs
> +
> +include $(RTE_SDK)/mk/rte.lib.mk
> diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
> new file mode 100644
> index 0000000..7ecdd17
> --- /dev/null
> +++ b/lib/librte_pmd_null/rte_eth_null.c
> @@ -0,0 +1,474 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright (C) IGEL Co.,Ltd.
> + *   All rights reserved.
> + *
> + *   Redistribution and use in source and binary forms, with or without
> + *   modification, are permitted provided that the following conditions
> + *   are met:
> + *
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in
> + *       the documentation and/or other materials provided with the
> + *       distribution.
> + *     * Neither the name of IGEL Co.,Ltd. nor the names of its
> + *       contributors may be used to endorse or promote products derived
> + *       from this software without specific prior written permission.
> + *
> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <rte_mbuf.h>
> +#include <rte_ethdev.h>
> +#include <rte_malloc.h>
> +#include <rte_memcpy.h>
> +#include <rte_dev.h>
> +#include <rte_kvargs.h>
> +
> +#define ETH_NULL_PACKET_SIZE_ARG	"size"
> +#define ETH_NULL_PACKET_COPY_ARG	"copy"
> +
> +static unsigned default_packet_size = 64;
> +static unsigned default_packet_copy;
> +
> +static const char const *valid_arguments[] = {
> +	ETH_NULL_PACKET_SIZE_ARG,
> +	ETH_NULL_PACKET_COPY_ARG,
> +	NULL
> +};
> +
> +struct pmd_internals;
> +
> +struct null_queue {
> +	struct pmd_internals *internals;
> +
> +	struct rte_mempool *mb_pool;
> +	struct rte_mbuf *dummy_packet;
> +
> +	rte_atomic64_t rx_pkts;
> +	rte_atomic64_t tx_pkts;
> +	rte_atomic64_t err_pkts;
> +};
> +
> +struct pmd_internals {
> +	unsigned packet_size;
> +	unsigned packet_copy;
> +	unsigned numa_node;
> +
> +	unsigned nb_rx_queues;
> +	unsigned nb_tx_queues;
> +
> +	struct null_queue rx_null_queues[1];
> +	struct null_queue tx_null_queues[1];
> +};
> +
> +
> +static struct ether_addr eth_addr = { .addr_bytes = {0} };
> +static const char *drivername = "Null PMD";
> +static struct rte_eth_link pmd_link = {
> +	.link_speed = 10000,
> +	.link_duplex = ETH_LINK_FULL_DUPLEX,
> +	.link_status = 0
> +};
> +
> +static uint16_t
> +eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
> +{
> +	int i;
> +	struct null_queue *h = q;
> +	unsigned packet_size = h->internals->packet_size;
> +
> +	for (i = 0; i < nb_bufs; i++) {
> +		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
> +		if (!bufs[i])
> +			break;
> +		bufs[i]->data_len = (uint16_t)packet_size;
> +		bufs[i]->pkt_len = packet_size;
> +		bufs[i]->nb_segs = 1;
> +		bufs[i]->next = NULL;
> +	}
> +
> +	rte_atomic64_add(&(h->rx_pkts), i);
> +
> +	return i;
> +}
> +
> +static uint16_t
> +eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
> +{
> +	int i;
> +	struct null_queue *h = q;
> +	unsigned packet_size = h->internals->packet_size;
> +
> +	for (i = 0; i < nb_bufs; i++) {
> +		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
> +		if (!bufs[i])
> +			break;
> +		rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,
> +					packet_size);
> +		bufs[i]->data_len = (uint16_t)packet_size;
> +		bufs[i]->pkt_len = packet_size;
> +		bufs[i]->nb_segs = 1;
> +		bufs[i]->next = NULL;
> +	}
> +
> +	rte_atomic64_add(&(h->rx_pkts), i);
> +
> +	return i;
> +}
> +
> +static uint16_t
> +eth_null_tx(void *q, struct rte_mbuf **bufs __rte_unused, uint16_t nb_bufs)
> +{
> +	int i;
> +	struct null_queue *h = q;
> +
> +	for (i = 0; i < nb_bufs; i++)
> +		rte_pktmbuf_free(bufs[i]);
> +
> +	rte_atomic64_add(&(h->tx_pkts), i);
> +
> +	return i;
> +}
> +
> +static uint16_t
> +eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
> +{
> +	int i;
> +	struct null_queue *h = q;
> +	unsigned packet_size = h->internals->packet_size;
> +
> +	for (i = 0; i < nb_bufs; i++) {
> +		rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *),
> +					packet_size);
> +		rte_pktmbuf_free(bufs[i]);
> +	}
> +
> +	rte_atomic64_add(&(h->tx_pkts), i);
> +
> +	return i;
> +}
> +
> +static int
> +eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; }
> +
> +static int
> +eth_dev_start(struct rte_eth_dev *dev)
> +{
> +	dev->data->dev_link.link_status = 1;
> +	return 0;
> +}
> +
> +static void
> +eth_dev_stop(struct rte_eth_dev *dev)
> +{
> +	dev->data->dev_link.link_status = 0;
> +}
> +
> +static int
> +eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
> +		uint16_t nb_rx_desc __rte_unused,
> +		unsigned int socket_id __rte_unused,
> +		const struct rte_eth_rxconf *rx_conf __rte_unused,
> +		struct rte_mempool *mb_pool __rte_unused)
> +{
> +	struct rte_mbuf *dummy_packet;
> +	struct pmd_internals *internals = dev->data->dev_private;
> +	unsigned packet_size = internals->packet_size;
> +
> +	if (rx_queue_id != 0)
> +			return -ENODEV;
> +
> +	internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool;
> +	dev->data->rx_queues[rx_queue_id] =
> +		&internals->rx_null_queues[rx_queue_id];
> +	dummy_packet = rte_zmalloc_socket(NULL,
> +			packet_size, 0, internals->numa_node);
> +	if (dummy_packet == NULL)
> +		return -ENOMEM;
> +
> +	internals->rx_null_queues[rx_queue_id].internals = internals;
> +	internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet;
> +
> +	return 0;
> +}
> +
> +static int
> +eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
> +		uint16_t nb_tx_desc __rte_unused,
> +		unsigned int socket_id __rte_unused,
> +		const struct rte_eth_txconf *tx_conf __rte_unused)
> +{
> +	struct rte_mbuf *dummy_packet;
> +	struct pmd_internals *internals = dev->data->dev_private;
> +	unsigned packet_size = internals->packet_size;
> +
> +	if (tx_queue_id != 0)
> +			return -ENODEV;
> +
> +	dev->data->tx_queues[tx_queue_id] =
> +		&internals->tx_null_queues[tx_queue_id];
> +	dummy_packet = rte_zmalloc_socket(NULL,
> +			packet_size, 0, internals->numa_node);
> +	if (dummy_packet == NULL)
> +		return -ENOMEM;
> +
> +	internals->tx_null_queues[tx_queue_id].internals = internals;
> +	internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet;
> +
> +	return 0;
> +}
> +
> +
> +static void
> +eth_dev_info(struct rte_eth_dev *dev,
> +		struct rte_eth_dev_info *dev_info)
> +{
> +	struct pmd_internals *internals = dev->data->dev_private;
> +
> +	dev_info->driver_name = drivername;
> +	dev_info->max_mac_addrs = 1;
> +	dev_info->max_rx_pktlen = (uint32_t)-1;
> +	dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;
> +	dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;
> +	dev_info->min_rx_bufsize = 0;
> +	dev_info->pci_dev = NULL;
> +}
> +
> +static void
> +eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)
> +{
> +	unsigned i;
> +	unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
> +	const struct pmd_internals *internal = dev->data->dev_private;
> +
> +	memset(igb_stats, 0, sizeof(*igb_stats));
> +	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
> +			i < internal->nb_rx_queues; i++) {
> +		igb_stats->q_ipackets[i] =
> +			internal->rx_null_queues[i].rx_pkts.cnt;
> +		rx_total += igb_stats->q_ipackets[i];
> +	}
> +
> +	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
> +			i < internal->nb_tx_queues; i++) {
> +		igb_stats->q_opackets[i] =
> +			internal->tx_null_queues[i].tx_pkts.cnt;
> +		igb_stats->q_errors[i] =
> +			internal->tx_null_queues[i].err_pkts.cnt;
> +		tx_total += igb_stats->q_opackets[i];
> +		tx_err_total += igb_stats->q_errors[i];
> +	}
> +
> +	igb_stats->ipackets = rx_total;
> +	igb_stats->opackets = tx_total;
> +	igb_stats->oerrors = tx_err_total;
> +}
> +
> +static void
> +eth_stats_reset(struct rte_eth_dev *dev)
> +{
> +	unsigned i;
> +	struct pmd_internals *internal = dev->data->dev_private;
> +
> +	for (i = 0; i < internal->nb_rx_queues; i++)
> +		internal->rx_null_queues[i].rx_pkts.cnt = 0;
> +	for (i = 0; i < internal->nb_tx_queues; i++) {
> +		internal->tx_null_queues[i].tx_pkts.cnt = 0;
> +		internal->tx_null_queues[i].err_pkts.cnt = 0;
> +	}
> +}
> +
> +static void
> +eth_queue_release(void *q __rte_unused) { ; }
> +static int
> +eth_link_update(struct rte_eth_dev *dev __rte_unused,
> +		int wait_to_complete __rte_unused) { return 0; }
> +
> +static struct eth_dev_ops ops = {
> +		.dev_start = eth_dev_start,
> +		.dev_stop = eth_dev_stop,
> +		.dev_configure = eth_dev_configure,
> +		.dev_infos_get = eth_dev_info,
> +		.rx_queue_setup = eth_rx_queue_setup,
> +		.tx_queue_setup = eth_tx_queue_setup,
> +		.rx_queue_release = eth_queue_release,
> +		.tx_queue_release = eth_queue_release,
> +		.link_update = eth_link_update,
> +		.stats_get = eth_stats_get,
> +		.stats_reset = eth_stats_reset,
> +};
> +
> +static int
> +eth_dev_null_create(const char *name __rte_unused,
> +		const unsigned numa_node,
> +		unsigned packet_size,
> +		unsigned packet_copy)
> +{
> +	const unsigned nb_rx_queues = 1;
> +	const unsigned nb_tx_queues = 1;
> +	struct rte_eth_dev_data *data = NULL;
> +	struct rte_pci_device *pci_dev = NULL;
> +	struct pmd_internals *internals = NULL;
> +	struct rte_eth_dev *eth_dev = NULL;
> +
> +	RTE_LOG(INFO, PMD, "Creating null ethdev on numa socket %u\n",
> +			numa_node);
> +
> +	/* now do all data allocation - for eth_dev structure, dummy pci driver
> +	 * and internal (private) data
> +	 */
> +	data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);
> +	if (data == NULL)
> +		goto error;
> +
> +	pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);
> +	if (pci_dev == NULL)
> +		goto error;
> +
> +	internals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node);
> +	if (internals == NULL)
> +		goto error;
> +
> +	/* reserve an ethdev entry */
> +	eth_dev = rte_eth_dev_allocate(name);
> +	if (eth_dev == NULL)
> +		goto error;
> +
> +	/* now put it all together
> +	 * - store queue data in internals,
> +	 * - store numa_node info in pci_driver
> +	 * - point eth_dev_data to internals and pci_driver
> +	 * - and point eth_dev structure to new eth_dev_data structure
> +	 */
> +	/* NOTE: we'll replace the data element, of originally allocated eth_dev
> +	 * so the nulls are local per-process */
> +
> +	internals->nb_rx_queues = nb_rx_queues;
> +	internals->nb_tx_queues = nb_tx_queues;
> +	internals->packet_size = packet_size;
> +	internals->packet_copy = packet_copy;
> +	internals->numa_node = numa_node;
> +
> +	pci_dev->numa_node = numa_node;
> +
> +	data->dev_private = internals;
> +	data->port_id = eth_dev->data->port_id;
> +	data->nb_rx_queues = (uint16_t)nb_rx_queues;
> +	data->nb_tx_queues = (uint16_t)nb_tx_queues;
> +	data->dev_link = pmd_link;
> +	data->mac_addrs = &eth_addr;
> +
> +	eth_dev->data = data;
> +	eth_dev->dev_ops = &ops;
> +	eth_dev->pci_dev = pci_dev;
> +
> +	/* finally assign rx and tx ops */
> +	if (packet_copy) {
> +		eth_dev->rx_pkt_burst = eth_null_copy_rx;
> +		eth_dev->tx_pkt_burst = eth_null_copy_tx;
> +	} else {
> +		eth_dev->rx_pkt_burst = eth_null_rx;
> +		eth_dev->tx_pkt_burst = eth_null_tx;
> +	}
> +
> +	return 0;
> +
> +error:
> +	if (data)
> +		rte_free(data);
> +	if (pci_dev)
> +		rte_free(pci_dev);
> +	if (internals)
> +		rte_free(internals);
> +	return -1;
> +}
> +
> +static inline int
> +get_packet_size_arg(const char *key __rte_unused,
> +		const char *value, void *extra_args)
> +{
> +	const char *a = value;
> +	unsigned *packet_size = extra_args;
> +
> +	*packet_size = (unsigned)strtoul(a, NULL, 0);
> +	if (*packet_size == UINT_MAX)
> +		return -1;
> +
> +	return 0;
> +}
> +
> +static inline int
> +get_packet_copy_arg(const char *key __rte_unused,
> +		const char *value, void *extra_args)
> +{
> +	const char *a = value;
> +	unsigned *packet_copy = extra_args;
> +
> +	*packet_copy = (unsigned)strtoul(a, NULL, 0);
> +	if (*packet_copy == UINT_MAX)
> +		return -1;
> +
> +	return 0;
> +}
> +
> +static int
> +rte_pmd_null_devinit(const char *name, const char *params)
> +{
> +	unsigned numa_node;
> +	unsigned packet_size = default_packet_size;
> +	unsigned packet_copy = default_packet_copy;
> +	struct rte_kvargs *kvlist;
> +	int ret;
> +
> +	RTE_LOG(INFO, PMD, "Initializing pmd_null for %s\n", name);
> +
> +	numa_node = rte_socket_id();
> +
> +	kvlist = rte_kvargs_parse(params, valid_arguments);
> +	if (kvlist == NULL)
> +		return -1;
> +
> +	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) {
> +
> +		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_SIZE_ARG,
> +				&get_packet_size_arg, &packet_size);
> +		if (ret < 0)
> +			return -1;
> +	}
> +
> +	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) {
> +
> +		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_COPY_ARG,
> +				&get_packet_copy_arg, &packet_copy);
> +		if (ret < 0)
> +			return -1;
> +	}
> +
> +	RTE_LOG(INFO, PMD, "Configure pmd_null: packet size is %d, "
> +			"packet copy is %s\n", packet_size,
> +			packet_copy ? "enabled" : "disabled");
> +
> +	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
> +}
> +
> +static struct rte_driver pmd_null_drv = {
> +	.name = "eth_null",
> +	.type = PMD_VDEV,
> +	.init = rte_pmd_null_devinit,
> +};
> +
> +PMD_REGISTER_DRIVER(pmd_null_drv);

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v3] librte_pmd_null: Add null PMD
       [not found]               ` <548FF0EA.3010501-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2014-12-16  8:47                 ` Thomas Monjalon
  2014-12-16  8:49                   ` Tetsuya Mukawa
  0 siblings, 1 reply; 60+ messages in thread
From: Thomas Monjalon @ 2014-12-16  8:47 UTC (permalink / raw)
  To: Tetsuya Mukawa; +Cc: dev-VfR2kkLFssw

2014-12-16 17:44, Tetsuya Mukawa:
> I've updated the null PMD to apply it to latest DPDK.
> Also I've sent a port hotplug patch for null PMD.

As explained in http://dpdk.org/dev#send, do not hesitate to
use --annotate to add this kind of changelog when sending patch.
Example:
	http://dpdk.org/ml/archives/dev/2014-December/010060.html

Thanks
-- 
Thomas

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v3] librte_pmd_null: Add null PMD
  2014-12-16  8:47                 ` Thomas Monjalon
@ 2014-12-16  8:49                   ` Tetsuya Mukawa
  0 siblings, 0 replies; 60+ messages in thread
From: Tetsuya Mukawa @ 2014-12-16  8:49 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev-VfR2kkLFssw

(2014/12/16 17:47), Thomas Monjalon wrote:
> 2014-12-16 17:44, Tetsuya Mukawa:
>> I've updated the null PMD to apply it to latest DPDK.
>> Also I've sent a port hotplug patch for null PMD.
> As explained in http://dpdk.org/dev#send, do not hesitate to
> use --annotate to add this kind of changelog when sending patch.
> Example:
> 	http://dpdk.org/ml/archives/dev/2014-December/010060.html
>
> Thanks

Thanks, I will do it next time.

Regards,
Tetsuya

^ permalink raw reply	[flat|nested] 60+ messages in thread

* [PATCH v4 1/2] librte_pmd_null: Add null PMD
       [not found]           ` <1418719167-8235-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  2014-12-16  8:44             ` Tetsuya Mukawa
@ 2015-01-20  3:00             ` Tetsuya Mukawa
       [not found]               ` <1421722821-18158-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  1 sibling, 1 reply; 60+ messages in thread
From: Tetsuya Mukawa @ 2015-01-20  3:00 UTC (permalink / raw)
  To: dev-VfR2kkLFssw

'null PMD' is a driver of the virtual device particulary designed to measure
performance of DPDK PMDs. When an application call rx, null PMD just allocates
mbufs and returns those. Also tx, the PMD just frees mbufs.

The PMD has following options.
- size: specify packe size allocated by RX. Default packet size is 64.
- copy: specify 1 or 0 to enable or disable copy while RX and TX.
	Default value is 0(disbaled).
	This option is used for emulating more realistic data transfer.
	Copy size is equal to packet size.

To use the PMD, enable CONFIG_RTE_BUILD_SHARED_LIB in config file. Then
compile the PMD as shared library. The library can be linked using '-d'
option when an application invokes.

Here is an example.
$ sudo ./testpmd -c f -n 4 -d librte_pmd_null.so \
	--vdev 'eth_null0' --vdev 'eth_null1' -- -i --no-flush-rx

If testpmd is compiled with CONFIG_RTE_BUILD_SHARED_LIB, it may need to
specify more libraries using '-d' option.

v4:
 - Fix memory leak.
   (Thanks to Iremonger, Bernard)

Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
---
 config/common_bsdapp               |   5 +
 config/common_linuxapp             |   5 +
 lib/Makefile                       |   1 +
 lib/librte_pmd_null/Makefile       |  58 +++++
 lib/librte_pmd_null/rte_eth_null.c | 485 +++++++++++++++++++++++++++++++++++++
 5 files changed, 554 insertions(+)
 create mode 100644 lib/librte_pmd_null/Makefile
 create mode 100644 lib/librte_pmd_null/rte_eth_null.c

diff --git a/config/common_bsdapp b/config/common_bsdapp
index 9177db1..fa849be 100644
--- a/config/common_bsdapp
+++ b/config/common_bsdapp
@@ -224,6 +224,11 @@ CONFIG_RTE_LIBRTE_PMD_PCAP=y
 CONFIG_RTE_LIBRTE_PMD_BOND=y
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/config/common_linuxapp b/config/common_linuxapp
index 27d05be..456fbfe 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -237,6 +237,11 @@ CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
 CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/lib/Makefile b/lib/Makefile
index 0ffc982..d246c53 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -52,6 +52,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += librte_pmd_virtio
 DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt
 DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += librte_vhost
+DIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += librte_pmd_null
 DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash
 DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm
 DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl
diff --git a/lib/librte_pmd_null/Makefile b/lib/librte_pmd_null/Makefile
new file mode 100644
index 0000000..0ec4db9
--- /dev/null
+++ b/lib/librte_pmd_null/Makefile
@@ -0,0 +1,58 @@
+#   BSD LICENSE
+#
+#   Copyright (C) IGEL Co.,Ltd.
+#   All rights reserved.
+#
+#   Redistribution and use in source and binary forms, with or without
+#   modification, are permitted provided that the following conditions
+#   are met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in
+#       the documentation and/or other materials provided with the
+#       distribution.
+#     * Neither the name of IGEL Co.,Ltd. nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_pmd_null.a
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += rte_eth_null.c
+
+#
+# Export include files
+#
+SYMLINK-y-include +=
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_malloc
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_kvargs
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
new file mode 100644
index 0000000..c54e90b
--- /dev/null
+++ b/lib/librte_pmd_null/rte_eth_null.c
@@ -0,0 +1,485 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright (C) IGEL Co.,Ltd.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of IGEL Co.,Ltd. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_dev.h>
+#include <rte_kvargs.h>
+
+#define ETH_NULL_PACKET_SIZE_ARG	"size"
+#define ETH_NULL_PACKET_COPY_ARG	"copy"
+
+static unsigned default_packet_size = 64;
+static unsigned default_packet_copy;
+
+static const char const *valid_arguments[] = {
+	ETH_NULL_PACKET_SIZE_ARG,
+	ETH_NULL_PACKET_COPY_ARG,
+	NULL
+};
+
+struct pmd_internals;
+
+struct null_queue {
+	struct pmd_internals *internals;
+
+	struct rte_mempool *mb_pool;
+	struct rte_mbuf *dummy_packet;
+
+	rte_atomic64_t rx_pkts;
+	rte_atomic64_t tx_pkts;
+	rte_atomic64_t err_pkts;
+};
+
+struct pmd_internals {
+	unsigned packet_size;
+	unsigned packet_copy;
+	unsigned numa_node;
+
+	unsigned nb_rx_queues;
+	unsigned nb_tx_queues;
+
+	struct null_queue rx_null_queues[1];
+	struct null_queue tx_null_queues[1];
+};
+
+
+static struct ether_addr eth_addr = { .addr_bytes = {0} };
+static const char *drivername = "Null PMD";
+static struct rte_eth_link pmd_link = {
+	.link_speed = 10000,
+	.link_duplex = ETH_LINK_FULL_DUPLEX,
+	.link_status = 0
+};
+
+static uint16_t
+eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,
+					packet_size);
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_tx(void *q, struct rte_mbuf **bufs __rte_unused, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+
+	for (i = 0; i < nb_bufs; i++)
+		rte_pktmbuf_free(bufs[i]);
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	for (i = 0; i < nb_bufs; i++) {
+		rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *),
+					packet_size);
+		rte_pktmbuf_free(bufs[i]);
+	}
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static int
+eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; }
+
+static int
+eth_dev_start(struct rte_eth_dev *dev)
+{
+	dev->data->dev_link.link_status = 1;
+	return 0;
+}
+
+static void
+eth_dev_stop(struct rte_eth_dev *dev)
+{
+	dev->data->dev_link.link_status = 0;
+}
+
+static int
+eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+		uint16_t nb_rx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_rxconf *rx_conf __rte_unused,
+		struct rte_mempool *mb_pool __rte_unused)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals = dev->data->dev_private;
+	unsigned packet_size = internals->packet_size;
+
+	if (rx_queue_id != 0)
+			return -ENODEV;
+
+	internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool;
+	dev->data->rx_queues[rx_queue_id] =
+		&internals->rx_null_queues[rx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->rx_null_queues[rx_queue_id].internals = internals;
+	internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+static int
+eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+		uint16_t nb_tx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals = dev->data->dev_private;
+	unsigned packet_size = internals->packet_size;
+
+	if (tx_queue_id != 0)
+			return -ENODEV;
+
+	dev->data->tx_queues[tx_queue_id] =
+		&internals->tx_null_queues[tx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->tx_null_queues[tx_queue_id].internals = internals;
+	internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+
+static void
+eth_dev_info(struct rte_eth_dev *dev,
+		struct rte_eth_dev_info *dev_info)
+{
+	struct pmd_internals *internals = dev->data->dev_private;
+
+	dev_info->driver_name = drivername;
+	dev_info->max_mac_addrs = 1;
+	dev_info->max_rx_pktlen = (uint32_t)-1;
+	dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;
+	dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;
+	dev_info->min_rx_bufsize = 0;
+	dev_info->pci_dev = NULL;
+}
+
+static void
+eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)
+{
+	unsigned i;
+	unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
+	const struct pmd_internals *internal = dev->data->dev_private;
+
+	memset(igb_stats, 0, sizeof(*igb_stats));
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_rx_queues; i++) {
+		igb_stats->q_ipackets[i] =
+			internal->rx_null_queues[i].rx_pkts.cnt;
+		rx_total += igb_stats->q_ipackets[i];
+	}
+
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_tx_queues; i++) {
+		igb_stats->q_opackets[i] =
+			internal->tx_null_queues[i].tx_pkts.cnt;
+		igb_stats->q_errors[i] =
+			internal->tx_null_queues[i].err_pkts.cnt;
+		tx_total += igb_stats->q_opackets[i];
+		tx_err_total += igb_stats->q_errors[i];
+	}
+
+	igb_stats->ipackets = rx_total;
+	igb_stats->opackets = tx_total;
+	igb_stats->oerrors = tx_err_total;
+}
+
+static void
+eth_stats_reset(struct rte_eth_dev *dev)
+{
+	unsigned i;
+	struct pmd_internals *internal = dev->data->dev_private;
+
+	for (i = 0; i < internal->nb_rx_queues; i++)
+		internal->rx_null_queues[i].rx_pkts.cnt = 0;
+	for (i = 0; i < internal->nb_tx_queues; i++) {
+		internal->tx_null_queues[i].tx_pkts.cnt = 0;
+		internal->tx_null_queues[i].err_pkts.cnt = 0;
+	}
+}
+
+static void
+eth_queue_release(void *q)
+{
+	struct null_queue *nq;
+
+	if (q == NULL)
+		return;
+
+	nq = q;
+	if (nq->dummy_packet)
+		rte_free(nq->dummy_packet);
+}
+
+static int
+eth_link_update(struct rte_eth_dev *dev __rte_unused,
+		int wait_to_complete __rte_unused) { return 0; }
+
+static struct eth_dev_ops ops = {
+		.dev_start = eth_dev_start,
+		.dev_stop = eth_dev_stop,
+		.dev_configure = eth_dev_configure,
+		.dev_infos_get = eth_dev_info,
+		.rx_queue_setup = eth_rx_queue_setup,
+		.tx_queue_setup = eth_tx_queue_setup,
+		.rx_queue_release = eth_queue_release,
+		.tx_queue_release = eth_queue_release,
+		.link_update = eth_link_update,
+		.stats_get = eth_stats_get,
+		.stats_reset = eth_stats_reset,
+};
+
+static int
+eth_dev_null_create(const char *name __rte_unused,
+		const unsigned numa_node,
+		unsigned packet_size,
+		unsigned packet_copy)
+{
+	const unsigned nb_rx_queues = 1;
+	const unsigned nb_tx_queues = 1;
+	struct rte_eth_dev_data *data = NULL;
+	struct rte_pci_device *pci_dev = NULL;
+	struct pmd_internals *internals = NULL;
+	struct rte_eth_dev *eth_dev = NULL;
+
+	RTE_LOG(INFO, PMD, "Creating null ethdev on numa socket %u\n",
+			numa_node);
+
+	/* now do all data allocation - for eth_dev structure, dummy pci driver
+	 * and internal (private) data
+	 */
+	data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);
+	if (data == NULL)
+		goto error;
+
+	pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);
+	if (pci_dev == NULL)
+		goto error;
+
+	internals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node);
+	if (internals == NULL)
+		goto error;
+
+	/* reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL);
+	if (eth_dev == NULL)
+		goto error;
+
+	/* now put it all together
+	 * - store queue data in internals,
+	 * - store numa_node info in pci_driver
+	 * - point eth_dev_data to internals and pci_driver
+	 * - and point eth_dev structure to new eth_dev_data structure
+	 */
+	/* NOTE: we'll replace the data element, of originally allocated eth_dev
+	 * so the nulls are local per-process */
+
+	internals->nb_rx_queues = nb_rx_queues;
+	internals->nb_tx_queues = nb_tx_queues;
+	internals->packet_size = packet_size;
+	internals->packet_copy = packet_copy;
+	internals->numa_node = numa_node;
+
+	pci_dev->numa_node = numa_node;
+
+	data->dev_private = internals;
+	data->port_id = eth_dev->data->port_id;
+	data->nb_rx_queues = (uint16_t)nb_rx_queues;
+	data->nb_tx_queues = (uint16_t)nb_tx_queues;
+	data->dev_link = pmd_link;
+	data->mac_addrs = &eth_addr;
+
+	eth_dev->data = data;
+	eth_dev->dev_ops = &ops;
+	eth_dev->pci_dev = pci_dev;
+
+	/* finally assign rx and tx ops */
+	if (packet_copy) {
+		eth_dev->rx_pkt_burst = eth_null_copy_rx;
+		eth_dev->tx_pkt_burst = eth_null_copy_tx;
+	} else {
+		eth_dev->rx_pkt_burst = eth_null_rx;
+		eth_dev->tx_pkt_burst = eth_null_tx;
+	}
+
+	return 0;
+
+error:
+	if (data)
+		rte_free(data);
+	if (pci_dev)
+		rte_free(pci_dev);
+	if (internals)
+		rte_free(internals);
+	return -1;
+}
+
+static inline int
+get_packet_size_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_size = extra_args;
+
+	*packet_size = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_size == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static inline int
+get_packet_copy_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_copy = extra_args;
+
+	*packet_copy = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_copy == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static int
+rte_pmd_null_devinit(const char *name, const char *params)
+{
+	unsigned numa_node;
+	unsigned packet_size = default_packet_size;
+	unsigned packet_copy = default_packet_copy;
+	struct rte_kvargs *kvlist;
+	int ret;
+
+	RTE_LOG(INFO, PMD, "Initializing pmd_null for %s\n", name);
+
+	numa_node = rte_socket_id();
+
+	kvlist = rte_kvargs_parse(params, valid_arguments);
+	if (kvlist == NULL)
+		return -1;
+
+	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) {
+
+		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_SIZE_ARG,
+				&get_packet_size_arg, &packet_size);
+		if (ret < 0)
+			return -1;
+	}
+
+	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) {
+
+		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_COPY_ARG,
+				&get_packet_copy_arg, &packet_copy);
+		if (ret < 0)
+			return -1;
+	}
+
+	RTE_LOG(INFO, PMD, "Configure pmd_null: packet size is %d, "
+			"packet copy is %s\n", packet_size,
+			packet_copy ? "enabled" : "disabled");
+
+	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
+}
+
+static struct rte_driver pmd_null_drv = {
+	.name = "eth_null",
+	.type = PMD_VDEV,
+	.init = rte_pmd_null_devinit,
+};
+
+PMD_REGISTER_DRIVER(pmd_null_drv);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v4 2/2] librte_pmd_null: Support port hotplug function
       [not found]               ` <1421722821-18158-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2015-01-20  3:00                 ` Tetsuya Mukawa
       [not found]                   ` <1421722821-18158-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  0 siblings, 1 reply; 60+ messages in thread
From: Tetsuya Mukawa @ 2015-01-20  3:00 UTC (permalink / raw)
  To: dev-VfR2kkLFssw

This patch adds port hotplug support to null PMD.

v4:
- Fix commit title.

Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
---
 lib/librte_pmd_null/rte_eth_null.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
index c54e90b..e9b1eee 100644
--- a/lib/librte_pmd_null/rte_eth_null.c
+++ b/lib/librte_pmd_null/rte_eth_null.c
@@ -292,6 +292,13 @@ eth_stats_reset(struct rte_eth_dev *dev)
 	}
 }
 
+static struct eth_driver rte_null_pmd = {
+	.pci_drv = {
+		.name = "rte_null_pmd",
+		.drv_flags = RTE_PCI_DRV_DETACHABLE,
+	},
+};
+
 static void
 eth_queue_release(void *q)
 {
@@ -382,10 +389,12 @@ eth_dev_null_create(const char *name __rte_unused,
 	data->nb_tx_queues = (uint16_t)nb_tx_queues;
 	data->dev_link = pmd_link;
 	data->mac_addrs = &eth_addr;
+	strncpy(data->name, eth_dev->data->name, strlen(eth_dev->data->name));
 
 	eth_dev->data = data;
 	eth_dev->dev_ops = &ops;
 	eth_dev->pci_dev = pci_dev;
+	eth_dev->driver = &rte_null_pmd;
 
 	/* finally assign rx and tx ops */
 	if (packet_copy) {
@@ -476,10 +485,33 @@ rte_pmd_null_devinit(const char *name, const char *params)
 	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
 }
 
+static int
+rte_pmd_null_devuninit(const char *name, const char *params __rte_unused)
+{
+	struct rte_eth_dev *eth_dev = NULL;
+
+	RTE_LOG(INFO, PMD, "Closing null ethdev on numa socket %u\n",
+			rte_socket_id());
+
+	/* reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocated(name);
+	if (eth_dev == NULL)
+		return -1;
+
+	rte_free(eth_dev->data->dev_private);
+	rte_free(eth_dev->data);
+	rte_free(eth_dev->pci_dev);
+
+	rte_eth_dev_free(name);
+
+	return 0;
+}
+
 static struct rte_driver pmd_null_drv = {
 	.name = "eth_null",
 	.type = PMD_VDEV,
 	.init = rte_pmd_null_devinit,
+	.uninit = rte_pmd_null_devuninit,
 };
 
 PMD_REGISTER_DRIVER(pmd_null_drv);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v6 1/2] librte_pmd_null: Add null PMD
       [not found]                   ` <1421722821-18158-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2015-02-06  4:38                     ` Tetsuya Mukawa
       [not found]                       ` <1423197495-1758-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  0 siblings, 1 reply; 60+ messages in thread
From: Tetsuya Mukawa @ 2015-02-06  4:38 UTC (permalink / raw)
  To: dev-VfR2kkLFssw

'null PMD' is a driver of the virtual device particulary designed to measure
performance of DPDK PMDs. When an application call rx, null PMD just allocates
mbufs and returns those. Also tx, the PMD just frees mbufs.

The PMD has following options.
- size: specify packe size allocated by RX. Default packet size is 64.
- copy: specify 1 or 0 to enable or disable copy while RX and TX.
	Default value is 0(disbaled).
	This option is used for emulating more realistic data transfer.
	Copy size is equal to packet size.

To use the PMD, enable CONFIG_RTE_BUILD_SHARED_LIB in config file. Then
compile the PMD as shared library. The library can be linked using '-d'
option when an application invokes.

Here is an example.
$ sudo ./testpmd -c f -n 4 -d librte_pmd_null.so \
	--vdev 'eth_null0' --vdev 'eth_null1' -- -i --no-flush-rx

If testpmd is compiled with CONFIG_RTE_BUILD_SHARED_LIB, it may need to
specify more libraries using '-d' option.

v4:
 - Fix memory leak.
   (Thanks to Iremonger, Bernard)

Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
---
 config/common_bsdapp               |   5 +
 config/common_linuxapp             |   5 +
 lib/Makefile                       |   1 +
 lib/librte_pmd_null/Makefile       |  58 +++++
 lib/librte_pmd_null/rte_eth_null.c | 485 +++++++++++++++++++++++++++++++++++++
 5 files changed, 554 insertions(+)
 create mode 100644 lib/librte_pmd_null/Makefile
 create mode 100644 lib/librte_pmd_null/rte_eth_null.c

diff --git a/config/common_bsdapp b/config/common_bsdapp
index 9177db1..fa849be 100644
--- a/config/common_bsdapp
+++ b/config/common_bsdapp
@@ -224,6 +224,11 @@ CONFIG_RTE_LIBRTE_PMD_PCAP=y
 CONFIG_RTE_LIBRTE_PMD_BOND=y
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/config/common_linuxapp b/config/common_linuxapp
index 27d05be..456fbfe 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -237,6 +237,11 @@ CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
 CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/lib/Makefile b/lib/Makefile
index 0ffc982..d246c53 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -52,6 +52,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += librte_pmd_virtio
 DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt
 DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += librte_vhost
+DIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += librte_pmd_null
 DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash
 DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm
 DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl
diff --git a/lib/librte_pmd_null/Makefile b/lib/librte_pmd_null/Makefile
new file mode 100644
index 0000000..0ec4db9
--- /dev/null
+++ b/lib/librte_pmd_null/Makefile
@@ -0,0 +1,58 @@
+#   BSD LICENSE
+#
+#   Copyright (C) IGEL Co.,Ltd.
+#   All rights reserved.
+#
+#   Redistribution and use in source and binary forms, with or without
+#   modification, are permitted provided that the following conditions
+#   are met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in
+#       the documentation and/or other materials provided with the
+#       distribution.
+#     * Neither the name of IGEL Co.,Ltd. nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_pmd_null.a
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += rte_eth_null.c
+
+#
+# Export include files
+#
+SYMLINK-y-include +=
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_malloc
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_kvargs
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
new file mode 100644
index 0000000..c54e90b
--- /dev/null
+++ b/lib/librte_pmd_null/rte_eth_null.c
@@ -0,0 +1,485 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright (C) IGEL Co.,Ltd.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of IGEL Co.,Ltd. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_dev.h>
+#include <rte_kvargs.h>
+
+#define ETH_NULL_PACKET_SIZE_ARG	"size"
+#define ETH_NULL_PACKET_COPY_ARG	"copy"
+
+static unsigned default_packet_size = 64;
+static unsigned default_packet_copy;
+
+static const char const *valid_arguments[] = {
+	ETH_NULL_PACKET_SIZE_ARG,
+	ETH_NULL_PACKET_COPY_ARG,
+	NULL
+};
+
+struct pmd_internals;
+
+struct null_queue {
+	struct pmd_internals *internals;
+
+	struct rte_mempool *mb_pool;
+	struct rte_mbuf *dummy_packet;
+
+	rte_atomic64_t rx_pkts;
+	rte_atomic64_t tx_pkts;
+	rte_atomic64_t err_pkts;
+};
+
+struct pmd_internals {
+	unsigned packet_size;
+	unsigned packet_copy;
+	unsigned numa_node;
+
+	unsigned nb_rx_queues;
+	unsigned nb_tx_queues;
+
+	struct null_queue rx_null_queues[1];
+	struct null_queue tx_null_queues[1];
+};
+
+
+static struct ether_addr eth_addr = { .addr_bytes = {0} };
+static const char *drivername = "Null PMD";
+static struct rte_eth_link pmd_link = {
+	.link_speed = 10000,
+	.link_duplex = ETH_LINK_FULL_DUPLEX,
+	.link_status = 0
+};
+
+static uint16_t
+eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,
+					packet_size);
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_tx(void *q, struct rte_mbuf **bufs __rte_unused, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+
+	for (i = 0; i < nb_bufs; i++)
+		rte_pktmbuf_free(bufs[i]);
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	for (i = 0; i < nb_bufs; i++) {
+		rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *),
+					packet_size);
+		rte_pktmbuf_free(bufs[i]);
+	}
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static int
+eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; }
+
+static int
+eth_dev_start(struct rte_eth_dev *dev)
+{
+	dev->data->dev_link.link_status = 1;
+	return 0;
+}
+
+static void
+eth_dev_stop(struct rte_eth_dev *dev)
+{
+	dev->data->dev_link.link_status = 0;
+}
+
+static int
+eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+		uint16_t nb_rx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_rxconf *rx_conf __rte_unused,
+		struct rte_mempool *mb_pool __rte_unused)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals = dev->data->dev_private;
+	unsigned packet_size = internals->packet_size;
+
+	if (rx_queue_id != 0)
+			return -ENODEV;
+
+	internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool;
+	dev->data->rx_queues[rx_queue_id] =
+		&internals->rx_null_queues[rx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->rx_null_queues[rx_queue_id].internals = internals;
+	internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+static int
+eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+		uint16_t nb_tx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals = dev->data->dev_private;
+	unsigned packet_size = internals->packet_size;
+
+	if (tx_queue_id != 0)
+			return -ENODEV;
+
+	dev->data->tx_queues[tx_queue_id] =
+		&internals->tx_null_queues[tx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->tx_null_queues[tx_queue_id].internals = internals;
+	internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+
+static void
+eth_dev_info(struct rte_eth_dev *dev,
+		struct rte_eth_dev_info *dev_info)
+{
+	struct pmd_internals *internals = dev->data->dev_private;
+
+	dev_info->driver_name = drivername;
+	dev_info->max_mac_addrs = 1;
+	dev_info->max_rx_pktlen = (uint32_t)-1;
+	dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;
+	dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;
+	dev_info->min_rx_bufsize = 0;
+	dev_info->pci_dev = NULL;
+}
+
+static void
+eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)
+{
+	unsigned i;
+	unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
+	const struct pmd_internals *internal = dev->data->dev_private;
+
+	memset(igb_stats, 0, sizeof(*igb_stats));
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_rx_queues; i++) {
+		igb_stats->q_ipackets[i] =
+			internal->rx_null_queues[i].rx_pkts.cnt;
+		rx_total += igb_stats->q_ipackets[i];
+	}
+
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_tx_queues; i++) {
+		igb_stats->q_opackets[i] =
+			internal->tx_null_queues[i].tx_pkts.cnt;
+		igb_stats->q_errors[i] =
+			internal->tx_null_queues[i].err_pkts.cnt;
+		tx_total += igb_stats->q_opackets[i];
+		tx_err_total += igb_stats->q_errors[i];
+	}
+
+	igb_stats->ipackets = rx_total;
+	igb_stats->opackets = tx_total;
+	igb_stats->oerrors = tx_err_total;
+}
+
+static void
+eth_stats_reset(struct rte_eth_dev *dev)
+{
+	unsigned i;
+	struct pmd_internals *internal = dev->data->dev_private;
+
+	for (i = 0; i < internal->nb_rx_queues; i++)
+		internal->rx_null_queues[i].rx_pkts.cnt = 0;
+	for (i = 0; i < internal->nb_tx_queues; i++) {
+		internal->tx_null_queues[i].tx_pkts.cnt = 0;
+		internal->tx_null_queues[i].err_pkts.cnt = 0;
+	}
+}
+
+static void
+eth_queue_release(void *q)
+{
+	struct null_queue *nq;
+
+	if (q == NULL)
+		return;
+
+	nq = q;
+	if (nq->dummy_packet)
+		rte_free(nq->dummy_packet);
+}
+
+static int
+eth_link_update(struct rte_eth_dev *dev __rte_unused,
+		int wait_to_complete __rte_unused) { return 0; }
+
+static struct eth_dev_ops ops = {
+		.dev_start = eth_dev_start,
+		.dev_stop = eth_dev_stop,
+		.dev_configure = eth_dev_configure,
+		.dev_infos_get = eth_dev_info,
+		.rx_queue_setup = eth_rx_queue_setup,
+		.tx_queue_setup = eth_tx_queue_setup,
+		.rx_queue_release = eth_queue_release,
+		.tx_queue_release = eth_queue_release,
+		.link_update = eth_link_update,
+		.stats_get = eth_stats_get,
+		.stats_reset = eth_stats_reset,
+};
+
+static int
+eth_dev_null_create(const char *name __rte_unused,
+		const unsigned numa_node,
+		unsigned packet_size,
+		unsigned packet_copy)
+{
+	const unsigned nb_rx_queues = 1;
+	const unsigned nb_tx_queues = 1;
+	struct rte_eth_dev_data *data = NULL;
+	struct rte_pci_device *pci_dev = NULL;
+	struct pmd_internals *internals = NULL;
+	struct rte_eth_dev *eth_dev = NULL;
+
+	RTE_LOG(INFO, PMD, "Creating null ethdev on numa socket %u\n",
+			numa_node);
+
+	/* now do all data allocation - for eth_dev structure, dummy pci driver
+	 * and internal (private) data
+	 */
+	data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);
+	if (data == NULL)
+		goto error;
+
+	pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);
+	if (pci_dev == NULL)
+		goto error;
+
+	internals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node);
+	if (internals == NULL)
+		goto error;
+
+	/* reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL);
+	if (eth_dev == NULL)
+		goto error;
+
+	/* now put it all together
+	 * - store queue data in internals,
+	 * - store numa_node info in pci_driver
+	 * - point eth_dev_data to internals and pci_driver
+	 * - and point eth_dev structure to new eth_dev_data structure
+	 */
+	/* NOTE: we'll replace the data element, of originally allocated eth_dev
+	 * so the nulls are local per-process */
+
+	internals->nb_rx_queues = nb_rx_queues;
+	internals->nb_tx_queues = nb_tx_queues;
+	internals->packet_size = packet_size;
+	internals->packet_copy = packet_copy;
+	internals->numa_node = numa_node;
+
+	pci_dev->numa_node = numa_node;
+
+	data->dev_private = internals;
+	data->port_id = eth_dev->data->port_id;
+	data->nb_rx_queues = (uint16_t)nb_rx_queues;
+	data->nb_tx_queues = (uint16_t)nb_tx_queues;
+	data->dev_link = pmd_link;
+	data->mac_addrs = &eth_addr;
+
+	eth_dev->data = data;
+	eth_dev->dev_ops = &ops;
+	eth_dev->pci_dev = pci_dev;
+
+	/* finally assign rx and tx ops */
+	if (packet_copy) {
+		eth_dev->rx_pkt_burst = eth_null_copy_rx;
+		eth_dev->tx_pkt_burst = eth_null_copy_tx;
+	} else {
+		eth_dev->rx_pkt_burst = eth_null_rx;
+		eth_dev->tx_pkt_burst = eth_null_tx;
+	}
+
+	return 0;
+
+error:
+	if (data)
+		rte_free(data);
+	if (pci_dev)
+		rte_free(pci_dev);
+	if (internals)
+		rte_free(internals);
+	return -1;
+}
+
+static inline int
+get_packet_size_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_size = extra_args;
+
+	*packet_size = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_size == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static inline int
+get_packet_copy_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_copy = extra_args;
+
+	*packet_copy = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_copy == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static int
+rte_pmd_null_devinit(const char *name, const char *params)
+{
+	unsigned numa_node;
+	unsigned packet_size = default_packet_size;
+	unsigned packet_copy = default_packet_copy;
+	struct rte_kvargs *kvlist;
+	int ret;
+
+	RTE_LOG(INFO, PMD, "Initializing pmd_null for %s\n", name);
+
+	numa_node = rte_socket_id();
+
+	kvlist = rte_kvargs_parse(params, valid_arguments);
+	if (kvlist == NULL)
+		return -1;
+
+	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) {
+
+		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_SIZE_ARG,
+				&get_packet_size_arg, &packet_size);
+		if (ret < 0)
+			return -1;
+	}
+
+	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) {
+
+		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_COPY_ARG,
+				&get_packet_copy_arg, &packet_copy);
+		if (ret < 0)
+			return -1;
+	}
+
+	RTE_LOG(INFO, PMD, "Configure pmd_null: packet size is %d, "
+			"packet copy is %s\n", packet_size,
+			packet_copy ? "enabled" : "disabled");
+
+	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
+}
+
+static struct rte_driver pmd_null_drv = {
+	.name = "eth_null",
+	.type = PMD_VDEV,
+	.init = rte_pmd_null_devinit,
+};
+
+PMD_REGISTER_DRIVER(pmd_null_drv);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v6 2/2] librte_pmd_null: Support port hotplug function
       [not found]                       ` <1423197495-1758-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2015-02-06  4:38                         ` Tetsuya Mukawa
       [not found]                           ` <1423197495-1758-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  2015-02-06 11:32                         ` [PATCH v6 1/2] librte_pmd_null: Add null PMD Iremonger, Bernard
  2015-02-12  2:44                         ` [PATCH v7 1/2] librte_pmd_null: Add Null PMD Tetsuya Mukawa
  2 siblings, 1 reply; 60+ messages in thread
From: Tetsuya Mukawa @ 2015-02-06  4:38 UTC (permalink / raw)
  To: dev-VfR2kkLFssw

This patch adds port hotplug support to null PMD.

v6:
 - Fix a paramter of rte_eth_dev_free().
v4:
- Fix commit title.

Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
---
 lib/librte_pmd_null/rte_eth_null.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
index c54e90b..6add7ce 100644
--- a/lib/librte_pmd_null/rte_eth_null.c
+++ b/lib/librte_pmd_null/rte_eth_null.c
@@ -292,6 +292,13 @@ eth_stats_reset(struct rte_eth_dev *dev)
 	}
 }
 
+static struct eth_driver rte_null_pmd = {
+	.pci_drv = {
+		.name = "rte_null_pmd",
+		.drv_flags = RTE_PCI_DRV_DETACHABLE,
+	},
+};
+
 static void
 eth_queue_release(void *q)
 {
@@ -382,10 +389,12 @@ eth_dev_null_create(const char *name __rte_unused,
 	data->nb_tx_queues = (uint16_t)nb_tx_queues;
 	data->dev_link = pmd_link;
 	data->mac_addrs = &eth_addr;
+	strncpy(data->name, eth_dev->data->name, strlen(eth_dev->data->name));
 
 	eth_dev->data = data;
 	eth_dev->dev_ops = &ops;
 	eth_dev->pci_dev = pci_dev;
+	eth_dev->driver = &rte_null_pmd;
 
 	/* finally assign rx and tx ops */
 	if (packet_copy) {
@@ -476,10 +485,33 @@ rte_pmd_null_devinit(const char *name, const char *params)
 	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
 }
 
+static int
+rte_pmd_null_devuninit(const char *name, const char *params __rte_unused)
+{
+	struct rte_eth_dev *eth_dev = NULL;
+
+	RTE_LOG(INFO, PMD, "Closing null ethdev on numa socket %u\n",
+			rte_socket_id());
+
+	/* reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocated(name);
+	if (eth_dev == NULL)
+		return -1;
+
+	rte_free(eth_dev->data->dev_private);
+	rte_free(eth_dev->data);
+	rte_free(eth_dev->pci_dev);
+
+	rte_eth_dev_free(eth_dev);
+
+	return 0;
+}
+
 static struct rte_driver pmd_null_drv = {
 	.name = "eth_null",
 	.type = PMD_VDEV,
 	.init = rte_pmd_null_devinit,
+	.uninit = rte_pmd_null_devuninit,
 };
 
 PMD_REGISTER_DRIVER(pmd_null_drv);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* Re: [PATCH v6 1/2] librte_pmd_null: Add null PMD
       [not found]                       ` <1423197495-1758-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  2015-02-06  4:38                         ` [PATCH v6 2/2] librte_pmd_null: Support port hotplug function Tetsuya Mukawa
@ 2015-02-06 11:32                         ` Iremonger, Bernard
       [not found]                           ` <8CEF83825BEC744B83065625E567D7C2049DDE4A-kPTMFJFq+rEMvF1YICWikbfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  2015-02-12  2:44                         ` [PATCH v7 1/2] librte_pmd_null: Add Null PMD Tetsuya Mukawa
  2 siblings, 1 reply; 60+ messages in thread
From: Iremonger, Bernard @ 2015-02-06 11:32 UTC (permalink / raw)
  To: Tetsuya Mukawa, dev-VfR2kkLFssw

Hi Tetsuya,

My comments are in line below.

> -----Original Message-----
> From: Tetsuya Mukawa [mailto:mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org]
> Sent: Friday, February 6, 2015 4:38 AM
> To: dev-VfR2kkLFssw@public.gmane.org
> Cc: Iremonger, Bernard; Tetsuya Mukawa
> Subject: [PATCH v6 1/2] librte_pmd_null: Add null PMD
> 
> 'null PMD' is a driver of the virtual device particulary designed to measure performance of DPDK
> PMDs. When an application call rx, null PMD just allocates mbufs and returns those. Also tx, the PMD
> just frees mbufs.
> 
> The PMD has following options.
> - size: specify packe size allocated by RX. Default packet size is 64.
> - copy: specify 1 or 0 to enable or disable copy while RX and TX.
> 	Default value is 0(disbaled).
> 	This option is used for emulating more realistic data transfer.
> 	Copy size is equal to packet size.
> 
> To use the PMD, enable CONFIG_RTE_BUILD_SHARED_LIB in config file. Then compile the PMD as
> shared library. The library can be linked using '-d'
> option when an application invokes.
> 
> Here is an example.
> $ sudo ./testpmd -c f -n 4 -d librte_pmd_null.so \
> 	--vdev 'eth_null0' --vdev 'eth_null1' -- -i --no-flush-rx
> 
> If testpmd is compiled with CONFIG_RTE_BUILD_SHARED_LIB, it may need to specify more libraries
> using '-d' option.
> 
> v4:
>  - Fix memory leak.
>    (Thanks to Iremonger, Bernard)
> 
> Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
> ---
>  config/common_bsdapp               |   5 +
>  config/common_linuxapp             |   5 +
>  lib/Makefile                       |   1 +
>  lib/librte_pmd_null/Makefile       |  58 +++++
>  lib/librte_pmd_null/rte_eth_null.c | 485 +++++++++++++++++++++++++++++++++++++
>  5 files changed, 554 insertions(+)
>  create mode 100644 lib/librte_pmd_null/Makefile  create mode 100644
> lib/librte_pmd_null/rte_eth_null.c
> 
> diff --git a/config/common_bsdapp b/config/common_bsdapp index 9177db1..fa849be 100644
> --- a/config/common_bsdapp
> +++ b/config/common_bsdapp
> @@ -224,6 +224,11 @@ CONFIG_RTE_LIBRTE_PMD_PCAP=y  CONFIG_RTE_LIBRTE_PMD_BOND=y
> 
>  #
> +# Compile null PMD
> +#
> +CONFIG_RTE_LIBRTE_PMD_NULL=y
> +
> +#
>  # Do prefetch of packet data within PMD driver receive function  #
> CONFIG_RTE_PMD_PACKET_PREFETCH=y diff --git a/config/common_linuxapp
> b/config/common_linuxapp index 27d05be..456fbfe 100644
> --- a/config/common_linuxapp
> +++ b/config/common_linuxapp
> @@ -237,6 +237,11 @@ CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
> CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
> 
>  #
> +# Compile null PMD
> +#
> +CONFIG_RTE_LIBRTE_PMD_NULL=y
> +
> +#
>  # Do prefetch of packet data within PMD driver receive function  #
> CONFIG_RTE_PMD_PACKET_PREFETCH=y diff --git a/lib/Makefile b/lib/Makefile index
> 0ffc982..d246c53 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -52,6 +52,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += librte_pmd_virtio
>  DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3
>  DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt
>  DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += librte_vhost
> +DIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += librte_pmd_null
>  DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash
>  DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm
>  DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl diff --git a/lib/librte_pmd_null/Makefile
> b/lib/librte_pmd_null/Makefile new file mode 100644 index 0000000..0ec4db9
> --- /dev/null
> +++ b/lib/librte_pmd_null/Makefile
> @@ -0,0 +1,58 @@
> +#   BSD LICENSE
> +#
> +#   Copyright (C) IGEL Co.,Ltd.
> +#   All rights reserved.
> +#
> +#   Redistribution and use in source and binary forms, with or without
> +#   modification, are permitted provided that the following conditions
> +#   are met:
> +#
> +#     * Redistributions of source code must retain the above copyright
> +#       notice, this list of conditions and the following disclaimer.
> +#     * Redistributions in binary form must reproduce the above copyright
> +#       notice, this list of conditions and the following disclaimer in
> +#       the documentation and/or other materials provided with the
> +#       distribution.
> +#     * Neither the name of IGEL Co.,Ltd. nor the names of its
> +#       contributors may be used to endorse or promote products derived
> +#       from this software without specific prior written permission.
> +#
> +#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> +#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> +#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> +#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> +#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> +#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> +#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> +#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> +#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> +#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> +#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +
> +include $(RTE_SDK)/mk/rte.vars.mk
> +
> +#
> +# library name
> +#
> +LIB = librte_pmd_null.a
> +
> +CFLAGS += -O3
> +CFLAGS += $(WERROR_FLAGS)
> +
> +#
> +# all source are stored in SRCS-y
> +#
> +SRCS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += rte_eth_null.c
> +
> +#
> +# Export include files
> +#
> +SYMLINK-y-include +=
> +
> +# this lib depends upon:
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_mbuf
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_ether
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_malloc
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_kvargs
> +
> +include $(RTE_SDK)/mk/rte.lib.mk
> diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
> new file mode 100644
> index 0000000..c54e90b
> --- /dev/null
> +++ b/lib/librte_pmd_null/rte_eth_null.c
> @@ -0,0 +1,485 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright (C) IGEL Co.,Ltd.
> + *   All rights reserved.
> + *
> + *   Redistribution and use in source and binary forms, with or without
> + *   modification, are permitted provided that the following conditions
> + *   are met:
> + *
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in
> + *       the documentation and/or other materials provided with the
> + *       distribution.
> + *     * Neither the name of IGEL Co.,Ltd. nor the names of its
> + *       contributors may be used to endorse or promote products derived
> + *       from this software without specific prior written permission.
> + *
> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <rte_mbuf.h>
> +#include <rte_ethdev.h>
> +#include <rte_malloc.h>
> +#include <rte_memcpy.h>
> +#include <rte_dev.h>
> +#include <rte_kvargs.h>
> +
> +#define ETH_NULL_PACKET_SIZE_ARG	"size"
> +#define ETH_NULL_PACKET_COPY_ARG	"copy"
> +
> +static unsigned default_packet_size = 64; static unsigned
> +default_packet_copy;
> +
> +static const char const *valid_arguments[] = {
> +	ETH_NULL_PACKET_SIZE_ARG,
> +	ETH_NULL_PACKET_COPY_ARG,
> +	NULL
> +};
> +
> +struct pmd_internals;
> +
> +struct null_queue {
> +	struct pmd_internals *internals;
> +
> +	struct rte_mempool *mb_pool;
> +	struct rte_mbuf *dummy_packet;
> +
> +	rte_atomic64_t rx_pkts;
> +	rte_atomic64_t tx_pkts;
> +	rte_atomic64_t err_pkts;
> +};
> +
> +struct pmd_internals {
> +	unsigned packet_size;
> +	unsigned packet_copy;
> +	unsigned numa_node;
> +
> +	unsigned nb_rx_queues;
> +	unsigned nb_tx_queues;
> +
> +	struct null_queue rx_null_queues[1];
> +	struct null_queue tx_null_queues[1];
> +};
> +
> +
> +static struct ether_addr eth_addr = { .addr_bytes = {0} }; static const
> +char *drivername = "Null PMD"; static struct rte_eth_link pmd_link = {
> +	.link_speed = 10000,
> +	.link_duplex = ETH_LINK_FULL_DUPLEX,
> +	.link_status = 0
> +};
> +
> +static uint16_t
> +eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) {
> +	int i;
> +	struct null_queue *h = q;
> +	unsigned packet_size = h->internals->packet_size;
> +
> +	for (i = 0; i < nb_bufs; i++) {
> +		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
> +		if (!bufs[i])
> +			break;

Should the code return an error here rather than break?

> +		bufs[i]->data_len = (uint16_t)packet_size;
> +		bufs[i]->pkt_len = packet_size;
> +		bufs[i]->nb_segs = 1;
> +		bufs[i]->next = NULL;
> +	}
> +
> +	rte_atomic64_add(&(h->rx_pkts), i);
> +
> +	return i;
> +}
> +
> +static uint16_t
> +eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) {
> +	int i;
> +	struct null_queue *h = q;
> +	unsigned packet_size = h->internals->packet_size;
> +
> +	for (i = 0; i < nb_bufs; i++) {
> +		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
> +		if (!bufs[i])
> +			break;

Should the code return an error here rather than break?

> +		rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,
> +					packet_size);
> +		bufs[i]->data_len = (uint16_t)packet_size;
> +		bufs[i]->pkt_len = packet_size;
> +		bufs[i]->nb_segs = 1;
> +		bufs[i]->next = NULL;
> +	}
> +
> +	rte_atomic64_add(&(h->rx_pkts), i);
> +
> +	return i;
> +}
> +
> +static uint16_t
> +eth_null_tx(void *q, struct rte_mbuf **bufs __rte_unused, uint16_t
> +nb_bufs) {
> +	int i;
> +	struct null_queue *h = q;

Input parameters q and bufs should be checked.

> +
> +	for (i = 0; i < nb_bufs; i++)
> +		rte_pktmbuf_free(bufs[i]);
> +
> +	rte_atomic64_add(&(h->tx_pkts), i);
> +
> +	return i;
> +}
> +
> +static uint16_t
> +eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) {
> +	int i;
> +	struct null_queue *h = q;
> +	unsigned packet_size = h->internals->packet_size;

Input parameters q and bufs should be checked.

> +
> +	for (i = 0; i < nb_bufs; i++) {
> +		rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *),
> +					packet_size);
> +		rte_pktmbuf_free(bufs[i]);
> +	}
> +
> +	rte_atomic64_add(&(h->tx_pkts), i);
> +
> +	return i;
> +}
> +
> +static int
> +eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; }
> +
> +static int
> +eth_dev_start(struct rte_eth_dev *dev)
> +{

Input parameter dev should be checked.

> +	dev->data->dev_link.link_status = 1;
> +	return 0;
> +}
> +
> +static void
> +eth_dev_stop(struct rte_eth_dev *dev)
> +{

Input parameter dev should be checked.

> +	dev->data->dev_link.link_status = 0;
> +}
> +
> +static int
> +eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
> +		uint16_t nb_rx_desc __rte_unused,
> +		unsigned int socket_id __rte_unused,
> +		const struct rte_eth_rxconf *rx_conf __rte_unused,
> +		struct rte_mempool *mb_pool __rte_unused) {
> +	struct rte_mbuf *dummy_packet;
> +	struct pmd_internals *internals = dev->data->dev_private;
> +	unsigned packet_size = internals->packet_size;
> +

Input parameter dev should be checked.

> +	if (rx_queue_id != 0)
> +			return -ENODEV;
> +
> +	internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool;
> +	dev->data->rx_queues[rx_queue_id] =
> +		&internals->rx_null_queues[rx_queue_id];
> +	dummy_packet = rte_zmalloc_socket(NULL,
> +			packet_size, 0, internals->numa_node);
> +	if (dummy_packet == NULL)
> +		return -ENOMEM;
> +
> +	internals->rx_null_queues[rx_queue_id].internals = internals;
> +	internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet;
> +
> +	return 0;
> +}
> +
> +static int
> +eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
> +		uint16_t nb_tx_desc __rte_unused,
> +		unsigned int socket_id __rte_unused,
> +		const struct rte_eth_txconf *tx_conf __rte_unused) {
> +	struct rte_mbuf *dummy_packet;
> +	struct pmd_internals *internals = dev->data->dev_private;
> +	unsigned packet_size = internals->packet_size;
> +

Input parameter dev should be checked.

> +	if (tx_queue_id != 0)
> +			return -ENODEV;
> +
> +	dev->data->tx_queues[tx_queue_id] =
> +		&internals->tx_null_queues[tx_queue_id];
> +	dummy_packet = rte_zmalloc_socket(NULL,
> +			packet_size, 0, internals->numa_node);
> +	if (dummy_packet == NULL)
> +		return -ENOMEM;
> +
> +	internals->tx_null_queues[tx_queue_id].internals = internals;
> +	internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet;
> +
> +	return 0;
> +}
> +
> +
> +static void
> +eth_dev_info(struct rte_eth_dev *dev,
> +		struct rte_eth_dev_info *dev_info)
> +{
> +	struct pmd_internals *internals = dev->data->dev_private;

Input parameters dev and dev_info should be checked.

> +
> +	dev_info->driver_name = drivername;
> +	dev_info->max_mac_addrs = 1;
> +	dev_info->max_rx_pktlen = (uint32_t)-1;
> +	dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;
> +	dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;
> +	dev_info->min_rx_bufsize = 0;
> +	dev_info->pci_dev = NULL;
> +}
> +
> +static void
> +eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)
> +{
> +	unsigned i;
> +	unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
> +	const struct pmd_internals *internal = dev->data->dev_private;

Input parameters dev and igb_stats should be checked.

> +
> +	memset(igb_stats, 0, sizeof(*igb_stats));
> +	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
> +			i < internal->nb_rx_queues; i++) {
> +		igb_stats->q_ipackets[i] =
> +			internal->rx_null_queues[i].rx_pkts.cnt;
> +		rx_total += igb_stats->q_ipackets[i];
> +	}
> +
> +	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
> +			i < internal->nb_tx_queues; i++) {
> +		igb_stats->q_opackets[i] =
> +			internal->tx_null_queues[i].tx_pkts.cnt;
> +		igb_stats->q_errors[i] =
> +			internal->tx_null_queues[i].err_pkts.cnt;
> +		tx_total += igb_stats->q_opackets[i];
> +		tx_err_total += igb_stats->q_errors[i];
> +	}
> +
> +	igb_stats->ipackets = rx_total;
> +	igb_stats->opackets = tx_total;
> +	igb_stats->oerrors = tx_err_total;
> +}
> +
> +static void
> +eth_stats_reset(struct rte_eth_dev *dev) {
> +	unsigned i;
> +	struct pmd_internals *internal = dev->data->dev_private;

Input parameter dev should be checked.

> +
> +	for (i = 0; i < internal->nb_rx_queues; i++)
> +		internal->rx_null_queues[i].rx_pkts.cnt = 0;
> +	for (i = 0; i < internal->nb_tx_queues; i++) {
> +		internal->tx_null_queues[i].tx_pkts.cnt = 0;
> +		internal->tx_null_queues[i].err_pkts.cnt = 0;
> +	}
> +}
> +
> +static void
> +eth_queue_release(void *q)
> +{
> +	struct null_queue *nq;
> +
> +	if (q == NULL)
> +		return;
> +
> +	nq = q;
> +	if (nq->dummy_packet)
> +		rte_free(nq->dummy_packet);
> +}
> +
> +static int
> +eth_link_update(struct rte_eth_dev *dev __rte_unused,
> +		int wait_to_complete __rte_unused) { return 0; }
> +
> +static struct eth_dev_ops ops = {
> +		.dev_start = eth_dev_start,
> +		.dev_stop = eth_dev_stop,
> +		.dev_configure = eth_dev_configure,
> +		.dev_infos_get = eth_dev_info,
> +		.rx_queue_setup = eth_rx_queue_setup,
> +		.tx_queue_setup = eth_tx_queue_setup,
> +		.rx_queue_release = eth_queue_release,
> +		.tx_queue_release = eth_queue_release,
> +		.link_update = eth_link_update,
> +		.stats_get = eth_stats_get,
> +		.stats_reset = eth_stats_reset,
> +};
> +
> +static int
> +eth_dev_null_create(const char *name __rte_unused,
> +		const unsigned numa_node,
> +		unsigned packet_size,
> +		unsigned packet_copy)
> +{
> +	const unsigned nb_rx_queues = 1;
> +	const unsigned nb_tx_queues = 1;
> +	struct rte_eth_dev_data *data = NULL;
> +	struct rte_pci_device *pci_dev = NULL;
> +	struct pmd_internals *internals = NULL;
> +	struct rte_eth_dev *eth_dev = NULL;
> +
> +	RTE_LOG(INFO, PMD, "Creating null ethdev on numa socket %u\n",
> +			numa_node);
> +
> +	/* now do all data allocation - for eth_dev structure, dummy pci driver
> +	 * and internal (private) data
> +	 */
> +	data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);
> +	if (data == NULL)
> +		goto error;
> +
> +	pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);
> +	if (pci_dev == NULL)
> +		goto error;
> +
> +	internals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node);
> +	if (internals == NULL)
> +		goto error;
> +
> +	/* reserve an ethdev entry */
> +	eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL);
> +	if (eth_dev == NULL)
> +		goto error;
> +
> +	/* now put it all together
> +	 * - store queue data in internals,
> +	 * - store numa_node info in pci_driver
> +	 * - point eth_dev_data to internals and pci_driver
> +	 * - and point eth_dev structure to new eth_dev_data structure
> +	 */
> +	/* NOTE: we'll replace the data element, of originally allocated eth_dev
> +	 * so the nulls are local per-process */
> +
> +	internals->nb_rx_queues = nb_rx_queues;
> +	internals->nb_tx_queues = nb_tx_queues;
> +	internals->packet_size = packet_size;
> +	internals->packet_copy = packet_copy;
> +	internals->numa_node = numa_node;
> +
> +	pci_dev->numa_node = numa_node;
> +
> +	data->dev_private = internals;
> +	data->port_id = eth_dev->data->port_id;
> +	data->nb_rx_queues = (uint16_t)nb_rx_queues;
> +	data->nb_tx_queues = (uint16_t)nb_tx_queues;
> +	data->dev_link = pmd_link;
> +	data->mac_addrs = &eth_addr;
> +
> +	eth_dev->data = data;
> +	eth_dev->dev_ops = &ops;
> +	eth_dev->pci_dev = pci_dev;
> +
> +	/* finally assign rx and tx ops */
> +	if (packet_copy) {
> +		eth_dev->rx_pkt_burst = eth_null_copy_rx;
> +		eth_dev->tx_pkt_burst = eth_null_copy_tx;
> +	} else {
> +		eth_dev->rx_pkt_burst = eth_null_rx;
> +		eth_dev->tx_pkt_burst = eth_null_tx;
> +	}
> +
> +	return 0;
> +
> +error:
> +	if (data)
> +		rte_free(data);
> +	if (pci_dev)
> +		rte_free(pci_dev);
> +	if (internals)
> +		rte_free(internals);
> +	return -1;
> +}
> +
> +static inline int
> +get_packet_size_arg(const char *key __rte_unused,
> +		const char *value, void *extra_args)
> +{
> +	const char *a = value;
> +	unsigned *packet_size = extra_args;

Parameters value and  extra_args should be checked.

> +
> +	*packet_size = (unsigned)strtoul(a, NULL, 0);
> +	if (*packet_size == UINT_MAX)
> +		return -1;
> +
> +	return 0;
> +}
> +
> +static inline int
> +get_packet_copy_arg(const char *key __rte_unused,
> +		const char *value, void *extra_args)
> +{
> +	const char *a = value;
> +	unsigned *packet_copy = extra_args;

Parameters value and  extra_args should be checked.

> +
> +	*packet_copy = (unsigned)strtoul(a, NULL, 0);
> +	if (*packet_copy == UINT_MAX)
> +		return -1;
> +
> +	return 0;
> +}
> +
> +static int
> +rte_pmd_null_devinit(const char *name, const char *params) {
> +	unsigned numa_node;
> +	unsigned packet_size = default_packet_size;
> +	unsigned packet_copy = default_packet_copy;
> +	struct rte_kvargs *kvlist;
> +	int ret;
> +

Input parameters name and params should be checked.

> +	RTE_LOG(INFO, PMD, "Initializing pmd_null for %s\n", name);
> +
> +	numa_node = rte_socket_id();
> +
> +	kvlist = rte_kvargs_parse(params, valid_arguments);
> +	if (kvlist == NULL)
> +		return -1;
> +
> +	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) {
> +
> +		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_SIZE_ARG,
> +				&get_packet_size_arg, &packet_size);
> +		if (ret < 0)
> +			return -1;
> +	}
> +
> +	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) {
> +
> +		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_COPY_ARG,
> +				&get_packet_copy_arg, &packet_copy);
> +		if (ret < 0)
> +			return -1;
> +	}
> +
> +	RTE_LOG(INFO, PMD, "Configure pmd_null: packet size is %d, "
> +			"packet copy is %s\n", packet_size,
> +			packet_copy ? "enabled" : "disabled");
> +
> +	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
> +}
> +
> +static struct rte_driver pmd_null_drv = {
> +	.name = "eth_null",
> +	.type = PMD_VDEV,
> +	.init = rte_pmd_null_devinit,
> +};
> +
> +PMD_REGISTER_DRIVER(pmd_null_drv);
> --
> 1.9.1
Regards,

Bernard.

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v6 2/2] librte_pmd_null: Support port hotplug function
       [not found]                           ` <1423197495-1758-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2015-02-06 11:37                             ` Iremonger, Bernard
  0 siblings, 0 replies; 60+ messages in thread
From: Iremonger, Bernard @ 2015-02-06 11:37 UTC (permalink / raw)
  To: Tetsuya Mukawa, dev-VfR2kkLFssw

Hi Tetsuya,

My comments are inline below.

> -----Original Message-----
> From: Tetsuya Mukawa [mailto:mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org]
> Sent: Friday, February 6, 2015 4:38 AM
> To: dev-VfR2kkLFssw@public.gmane.org
> Cc: Iremonger, Bernard; Tetsuya Mukawa
> Subject: [PATCH v6 2/2] librte_pmd_null: Support port hotplug function
> 
> This patch adds port hotplug support to null PMD.
> 
> v6:
>  - Fix a paramter of rte_eth_dev_free().
> v4:
> - Fix commit title.
> 
> Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
> ---
>  lib/librte_pmd_null/rte_eth_null.c | 32 ++++++++++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
> 
> diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
> index c54e90b..6add7ce 100644
> --- a/lib/librte_pmd_null/rte_eth_null.c
> +++ b/lib/librte_pmd_null/rte_eth_null.c
> @@ -292,6 +292,13 @@ eth_stats_reset(struct rte_eth_dev *dev)
>  	}
>  }
> 
> +static struct eth_driver rte_null_pmd = {
> +	.pci_drv = {
> +		.name = "rte_null_pmd",
> +		.drv_flags = RTE_PCI_DRV_DETACHABLE,
> +	},
> +};
> +
>  static void
>  eth_queue_release(void *q)
>  {
> @@ -382,10 +389,12 @@ eth_dev_null_create(const char *name __rte_unused,
>  	data->nb_tx_queues = (uint16_t)nb_tx_queues;
>  	data->dev_link = pmd_link;
>  	data->mac_addrs = &eth_addr;
> +	strncpy(data->name, eth_dev->data->name, strlen(eth_dev->data->name));
> 
>  	eth_dev->data = data;
>  	eth_dev->dev_ops = &ops;
>  	eth_dev->pci_dev = pci_dev;
> +	eth_dev->driver = &rte_null_pmd;
> 
>  	/* finally assign rx and tx ops */
>  	if (packet_copy) {
> @@ -476,10 +485,33 @@ rte_pmd_null_devinit(const char *name, const char *params)
>  	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);  }
> 
> +static int
> +rte_pmd_null_devuninit(const char *name, const char *params
> +__rte_unused) {
> +	struct rte_eth_dev *eth_dev = NULL;

Input parameter name should be checked.

> +
> +	RTE_LOG(INFO, PMD, "Closing null ethdev on numa socket %u\n",
> +			rte_socket_id());
> +
> +	/* reserve an ethdev entry */
> +	eth_dev = rte_eth_dev_allocated(name);
> +	if (eth_dev == NULL)
> +		return -1;
> +
> +	rte_free(eth_dev->data->dev_private);
> +	rte_free(eth_dev->data);
> +	rte_free(eth_dev->pci_dev);
> +
> +	rte_eth_dev_free(eth_dev);
> +
> +	return 0;
> +}
> +
>  static struct rte_driver pmd_null_drv = {
>  	.name = "eth_null",
>  	.type = PMD_VDEV,
>  	.init = rte_pmd_null_devinit,
> +	.uninit = rte_pmd_null_devuninit,
>  };
> 
>  PMD_REGISTER_DRIVER(pmd_null_drv);
> --
> 1.9.1

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v6 1/2] librte_pmd_null: Add null PMD
       [not found]                           ` <8CEF83825BEC744B83065625E567D7C2049DDE4A-kPTMFJFq+rEMvF1YICWikbfspsVTdybXVpNB7YpNyf8@public.gmane.org>
@ 2015-02-09  8:54                             ` Tetsuya Mukawa
  0 siblings, 0 replies; 60+ messages in thread
From: Tetsuya Mukawa @ 2015-02-09  8:54 UTC (permalink / raw)
  To: Iremonger, Bernard, dev-VfR2kkLFssw

On 2015/02/06 20:32, Iremonger, Bernard wrote:
> Hi Tetsuya,
>
> My comments are in line below.
>
>> -----Original Message-----
>> From: Tetsuya Mukawa [mailto:mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org]
>> Sent: Friday, February 6, 2015 4:38 AM
>> To: dev-VfR2kkLFssw@public.gmane.org
>> Cc: Iremonger, Bernard; Tetsuya Mukawa
>> Subject: [PATCH v6 1/2] librte_pmd_null: Add null PMD
>>
>> 'null PMD' is a driver of the virtual device particulary designed to measure performance of DPDK
>> PMDs. When an application call rx, null PMD just allocates mbufs and returns those. Also tx, the PMD
>> just frees mbufs.
>>
>> The PMD has following options.
>> - size: specify packe size allocated by RX. Default packet size is 64.
>> - copy: specify 1 or 0 to enable or disable copy while RX and TX.
>> 	Default value is 0(disbaled).
>> 	This option is used for emulating more realistic data transfer.
>> 	Copy size is equal to packet size.
>>
>> To use the PMD, enable CONFIG_RTE_BUILD_SHARED_LIB in config file. Then compile the PMD as
>> shared library. The library can be linked using '-d'
>> option when an application invokes.
>>
>> Here is an example.
>> $ sudo ./testpmd -c f -n 4 -d librte_pmd_null.so \
>> 	--vdev 'eth_null0' --vdev 'eth_null1' -- -i --no-flush-rx
>>
>> If testpmd is compiled with CONFIG_RTE_BUILD_SHARED_LIB, it may need to specify more libraries
>> using '-d' option.
>>
>> v4:
>>  - Fix memory leak.
>>    (Thanks to Iremonger, Bernard)
>>
>> Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
>> ---
>>  config/common_bsdapp               |   5 +
>>  config/common_linuxapp             |   5 +
>>  lib/Makefile                       |   1 +
>>  lib/librte_pmd_null/Makefile       |  58 +++++
>>  lib/librte_pmd_null/rte_eth_null.c | 485 +++++++++++++++++++++++++++++++++++++
>>  5 files changed, 554 insertions(+)
>>  create mode 100644 lib/librte_pmd_null/Makefile  create mode 100644
>> lib/librte_pmd_null/rte_eth_null.c
>>
>> diff --git a/config/common_bsdapp b/config/common_bsdapp index 9177db1..fa849be 100644
>> --- a/config/common_bsdapp
>> +++ b/config/common_bsdapp
>> @@ -224,6 +224,11 @@ CONFIG_RTE_LIBRTE_PMD_PCAP=y  CONFIG_RTE_LIBRTE_PMD_BOND=y
>>
>>  #
>> +# Compile null PMD
>> +#
>> +CONFIG_RTE_LIBRTE_PMD_NULL=y
>> +
>> +#
>>  # Do prefetch of packet data within PMD driver receive function  #
>> CONFIG_RTE_PMD_PACKET_PREFETCH=y diff --git a/config/common_linuxapp
>> b/config/common_linuxapp index 27d05be..456fbfe 100644
>> --- a/config/common_linuxapp
>> +++ b/config/common_linuxapp
>> @@ -237,6 +237,11 @@ CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
>> CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
>>
>>  #
>> +# Compile null PMD
>> +#
>> +CONFIG_RTE_LIBRTE_PMD_NULL=y
>> +
>> +#
>>  # Do prefetch of packet data within PMD driver receive function  #
>> CONFIG_RTE_PMD_PACKET_PREFETCH=y diff --git a/lib/Makefile b/lib/Makefile index
>> 0ffc982..d246c53 100644
>> --- a/lib/Makefile
>> +++ b/lib/Makefile
>> @@ -52,6 +52,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += librte_pmd_virtio
>>  DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3
>>  DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt
>>  DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += librte_vhost
>> +DIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += librte_pmd_null
>>  DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash
>>  DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm
>>  DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl diff --git a/lib/librte_pmd_null/Makefile
>> b/lib/librte_pmd_null/Makefile new file mode 100644 index 0000000..0ec4db9
>> --- /dev/null
>> +++ b/lib/librte_pmd_null/Makefile
>> @@ -0,0 +1,58 @@
>> +#   BSD LICENSE
>> +#
>> +#   Copyright (C) IGEL Co.,Ltd.
>> +#   All rights reserved.
>> +#
>> +#   Redistribution and use in source and binary forms, with or without
>> +#   modification, are permitted provided that the following conditions
>> +#   are met:
>> +#
>> +#     * Redistributions of source code must retain the above copyright
>> +#       notice, this list of conditions and the following disclaimer.
>> +#     * Redistributions in binary form must reproduce the above copyright
>> +#       notice, this list of conditions and the following disclaimer in
>> +#       the documentation and/or other materials provided with the
>> +#       distribution.
>> +#     * Neither the name of IGEL Co.,Ltd. nor the names of its
>> +#       contributors may be used to endorse or promote products derived
>> +#       from this software without specific prior written permission.
>> +#
>> +#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
>> +#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
>> +#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
>> +#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
>> +#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
>> +#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
>> +#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
>> +#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
>> +#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
>> +#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
>> +#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
>> +
>> +include $(RTE_SDK)/mk/rte.vars.mk
>> +
>> +#
>> +# library name
>> +#
>> +LIB = librte_pmd_null.a
>> +
>> +CFLAGS += -O3
>> +CFLAGS += $(WERROR_FLAGS)
>> +
>> +#
>> +# all source are stored in SRCS-y
>> +#
>> +SRCS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += rte_eth_null.c
>> +
>> +#
>> +# Export include files
>> +#
>> +SYMLINK-y-include +=
>> +
>> +# this lib depends upon:
>> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_mbuf
>> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_ether
>> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_malloc
>> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_kvargs
>> +
>> +include $(RTE_SDK)/mk/rte.lib.mk
>> diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
>> new file mode 100644
>> index 0000000..c54e90b
>> --- /dev/null
>> +++ b/lib/librte_pmd_null/rte_eth_null.c
>> @@ -0,0 +1,485 @@
>> +/*-
>> + *   BSD LICENSE
>> + *
>> + *   Copyright (C) IGEL Co.,Ltd.
>> + *   All rights reserved.
>> + *
>> + *   Redistribution and use in source and binary forms, with or without
>> + *   modification, are permitted provided that the following conditions
>> + *   are met:
>> + *
>> + *     * Redistributions of source code must retain the above copyright
>> + *       notice, this list of conditions and the following disclaimer.
>> + *     * Redistributions in binary form must reproduce the above copyright
>> + *       notice, this list of conditions and the following disclaimer in
>> + *       the documentation and/or other materials provided with the
>> + *       distribution.
>> + *     * Neither the name of IGEL Co.,Ltd. nor the names of its
>> + *       contributors may be used to endorse or promote products derived
>> + *       from this software without specific prior written permission.
>> + *
>> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
>> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
>> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
>> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
>> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
>> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
>> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
>> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
>> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
>> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
>> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
>> + */
>> +
>> +#include <rte_mbuf.h>
>> +#include <rte_ethdev.h>
>> +#include <rte_malloc.h>
>> +#include <rte_memcpy.h>
>> +#include <rte_dev.h>
>> +#include <rte_kvargs.h>
>> +
>> +#define ETH_NULL_PACKET_SIZE_ARG	"size"
>> +#define ETH_NULL_PACKET_COPY_ARG	"copy"
>> +
>> +static unsigned default_packet_size = 64; static unsigned
>> +default_packet_copy;
>> +
>> +static const char const *valid_arguments[] = {
>> +	ETH_NULL_PACKET_SIZE_ARG,
>> +	ETH_NULL_PACKET_COPY_ARG,
>> +	NULL
>> +};
>> +
>> +struct pmd_internals;
>> +
>> +struct null_queue {
>> +	struct pmd_internals *internals;
>> +
>> +	struct rte_mempool *mb_pool;
>> +	struct rte_mbuf *dummy_packet;
>> +
>> +	rte_atomic64_t rx_pkts;
>> +	rte_atomic64_t tx_pkts;
>> +	rte_atomic64_t err_pkts;
>> +};
>> +
>> +struct pmd_internals {
>> +	unsigned packet_size;
>> +	unsigned packet_copy;
>> +	unsigned numa_node;
>> +
>> +	unsigned nb_rx_queues;
>> +	unsigned nb_tx_queues;
>> +
>> +	struct null_queue rx_null_queues[1];
>> +	struct null_queue tx_null_queues[1];
>> +};
>> +
>> +
>> +static struct ether_addr eth_addr = { .addr_bytes = {0} }; static const
>> +char *drivername = "Null PMD"; static struct rte_eth_link pmd_link = {
>> +	.link_speed = 10000,
>> +	.link_duplex = ETH_LINK_FULL_DUPLEX,
>> +	.link_status = 0
>> +};
>> +
>> +static uint16_t
>> +eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) {
>> +	int i;
>> +	struct null_queue *h = q;
>> +	unsigned packet_size = h->internals->packet_size;
>> +
>> +	for (i = 0; i < nb_bufs; i++) {
>> +		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
>> +		if (!bufs[i])
>> +			break;
> Should the code return an error here rather than break?

Hi Bernard,

I appreciate for your comments.

I guess it's not an error.
The function should return the number of packets actually allocated.

>
>> +		bufs[i]->data_len = (uint16_t)packet_size;
>> +		bufs[i]->pkt_len = packet_size;
>> +		bufs[i]->nb_segs = 1;
>> +		bufs[i]->next = NULL;
>> +	}
>> +
>> +	rte_atomic64_add(&(h->rx_pkts), i);
>> +
>> +	return i;
>> +}
>> +
>> +static uint16_t
>> +eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) {
>> +	int i;
>> +	struct null_queue *h = q;
>> +	unsigned packet_size = h->internals->packet_size;
>> +
>> +	for (i = 0; i < nb_bufs; i++) {
>> +		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
>> +		if (!bufs[i])
>> +			break;
> Should the code return an error here rather than break?

Also, the function should return the number of packets actually sent.

>> +		rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,
>> +					packet_size);
>> +		bufs[i]->data_len = (uint16_t)packet_size;
>> +		bufs[i]->pkt_len = packet_size;
>> +		bufs[i]->nb_segs = 1;
>> +		bufs[i]->next = NULL;
>> +	}
>> +
>> +	rte_atomic64_add(&(h->rx_pkts), i);
>> +
>> +	return i;
>> +}
>> +
>> +static uint16_t
>> +eth_null_tx(void *q, struct rte_mbuf **bufs __rte_unused, uint16_t
>> +nb_bufs) {
>> +	int i;
>> +	struct null_queue *h = q;
> Input parameters q and bufs should be checked.

Thanks, I will fix these suggestions.

Regards,
Tetsuya

>> +
>> +	for (i = 0; i < nb_bufs; i++)
>> +		rte_pktmbuf_free(bufs[i]);
>> +
>> +	rte_atomic64_add(&(h->tx_pkts), i);
>> +
>> +	return i;
>> +}
>> +
>> +static uint16_t
>> +eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) {
>> +	int i;
>> +	struct null_queue *h = q;
>> +	unsigned packet_size = h->internals->packet_size;
> Input parameters q and bufs should be checked.
>
>> +
>> +	for (i = 0; i < nb_bufs; i++) {
>> +		rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *),
>> +					packet_size);
>> +		rte_pktmbuf_free(bufs[i]);
>> +	}
>> +
>> +	rte_atomic64_add(&(h->tx_pkts), i);
>> +
>> +	return i;
>> +}
>> +
>> +static int
>> +eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; }
>> +
>> +static int
>> +eth_dev_start(struct rte_eth_dev *dev)
>> +{
> Input parameter dev should be checked.
>
>> +	dev->data->dev_link.link_status = 1;
>> +	return 0;
>> +}
>> +
>> +static void
>> +eth_dev_stop(struct rte_eth_dev *dev)
>> +{
> Input parameter dev should be checked.
>
>> +	dev->data->dev_link.link_status = 0;
>> +}
>> +
>> +static int
>> +eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
>> +		uint16_t nb_rx_desc __rte_unused,
>> +		unsigned int socket_id __rte_unused,
>> +		const struct rte_eth_rxconf *rx_conf __rte_unused,
>> +		struct rte_mempool *mb_pool __rte_unused) {
>> +	struct rte_mbuf *dummy_packet;
>> +	struct pmd_internals *internals = dev->data->dev_private;
>> +	unsigned packet_size = internals->packet_size;
>> +
> Input parameter dev should be checked.
>
>> +	if (rx_queue_id != 0)
>> +			return -ENODEV;
>> +
>> +	internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool;
>> +	dev->data->rx_queues[rx_queue_id] =
>> +		&internals->rx_null_queues[rx_queue_id];
>> +	dummy_packet = rte_zmalloc_socket(NULL,
>> +			packet_size, 0, internals->numa_node);
>> +	if (dummy_packet == NULL)
>> +		return -ENOMEM;
>> +
>> +	internals->rx_null_queues[rx_queue_id].internals = internals;
>> +	internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet;
>> +
>> +	return 0;
>> +}
>> +
>> +static int
>> +eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
>> +		uint16_t nb_tx_desc __rte_unused,
>> +		unsigned int socket_id __rte_unused,
>> +		const struct rte_eth_txconf *tx_conf __rte_unused) {
>> +	struct rte_mbuf *dummy_packet;
>> +	struct pmd_internals *internals = dev->data->dev_private;
>> +	unsigned packet_size = internals->packet_size;
>> +
> Input parameter dev should be checked.
>
>> +	if (tx_queue_id != 0)
>> +			return -ENODEV;
>> +
>> +	dev->data->tx_queues[tx_queue_id] =
>> +		&internals->tx_null_queues[tx_queue_id];
>> +	dummy_packet = rte_zmalloc_socket(NULL,
>> +			packet_size, 0, internals->numa_node);
>> +	if (dummy_packet == NULL)
>> +		return -ENOMEM;
>> +
>> +	internals->tx_null_queues[tx_queue_id].internals = internals;
>> +	internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet;
>> +
>> +	return 0;
>> +}
>> +
>> +
>> +static void
>> +eth_dev_info(struct rte_eth_dev *dev,
>> +		struct rte_eth_dev_info *dev_info)
>> +{
>> +	struct pmd_internals *internals = dev->data->dev_private;
> Input parameters dev and dev_info should be checked.
>
>> +
>> +	dev_info->driver_name = drivername;
>> +	dev_info->max_mac_addrs = 1;
>> +	dev_info->max_rx_pktlen = (uint32_t)-1;
>> +	dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;
>> +	dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;
>> +	dev_info->min_rx_bufsize = 0;
>> +	dev_info->pci_dev = NULL;
>> +}
>> +
>> +static void
>> +eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)
>> +{
>> +	unsigned i;
>> +	unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
>> +	const struct pmd_internals *internal = dev->data->dev_private;
> Input parameters dev and igb_stats should be checked.
>
>> +
>> +	memset(igb_stats, 0, sizeof(*igb_stats));
>> +	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
>> +			i < internal->nb_rx_queues; i++) {
>> +		igb_stats->q_ipackets[i] =
>> +			internal->rx_null_queues[i].rx_pkts.cnt;
>> +		rx_total += igb_stats->q_ipackets[i];
>> +	}
>> +
>> +	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
>> +			i < internal->nb_tx_queues; i++) {
>> +		igb_stats->q_opackets[i] =
>> +			internal->tx_null_queues[i].tx_pkts.cnt;
>> +		igb_stats->q_errors[i] =
>> +			internal->tx_null_queues[i].err_pkts.cnt;
>> +		tx_total += igb_stats->q_opackets[i];
>> +		tx_err_total += igb_stats->q_errors[i];
>> +	}
>> +
>> +	igb_stats->ipackets = rx_total;
>> +	igb_stats->opackets = tx_total;
>> +	igb_stats->oerrors = tx_err_total;
>> +}
>> +
>> +static void
>> +eth_stats_reset(struct rte_eth_dev *dev) {
>> +	unsigned i;
>> +	struct pmd_internals *internal = dev->data->dev_private;
> Input parameter dev should be checked.
>
>> +
>> +	for (i = 0; i < internal->nb_rx_queues; i++)
>> +		internal->rx_null_queues[i].rx_pkts.cnt = 0;
>> +	for (i = 0; i < internal->nb_tx_queues; i++) {
>> +		internal->tx_null_queues[i].tx_pkts.cnt = 0;
>> +		internal->tx_null_queues[i].err_pkts.cnt = 0;
>> +	}
>> +}
>> +
>> +static void
>> +eth_queue_release(void *q)
>> +{
>> +	struct null_queue *nq;
>> +
>> +	if (q == NULL)
>> +		return;
>> +
>> +	nq = q;
>> +	if (nq->dummy_packet)
>> +		rte_free(nq->dummy_packet);
>> +}
>> +
>> +static int
>> +eth_link_update(struct rte_eth_dev *dev __rte_unused,
>> +		int wait_to_complete __rte_unused) { return 0; }
>> +
>> +static struct eth_dev_ops ops = {
>> +		.dev_start = eth_dev_start,
>> +		.dev_stop = eth_dev_stop,
>> +		.dev_configure = eth_dev_configure,
>> +		.dev_infos_get = eth_dev_info,
>> +		.rx_queue_setup = eth_rx_queue_setup,
>> +		.tx_queue_setup = eth_tx_queue_setup,
>> +		.rx_queue_release = eth_queue_release,
>> +		.tx_queue_release = eth_queue_release,
>> +		.link_update = eth_link_update,
>> +		.stats_get = eth_stats_get,
>> +		.stats_reset = eth_stats_reset,
>> +};
>> +
>> +static int
>> +eth_dev_null_create(const char *name __rte_unused,
>> +		const unsigned numa_node,
>> +		unsigned packet_size,
>> +		unsigned packet_copy)
>> +{
>> +	const unsigned nb_rx_queues = 1;
>> +	const unsigned nb_tx_queues = 1;
>> +	struct rte_eth_dev_data *data = NULL;
>> +	struct rte_pci_device *pci_dev = NULL;
>> +	struct pmd_internals *internals = NULL;
>> +	struct rte_eth_dev *eth_dev = NULL;
>> +
>> +	RTE_LOG(INFO, PMD, "Creating null ethdev on numa socket %u\n",
>> +			numa_node);
>> +
>> +	/* now do all data allocation - for eth_dev structure, dummy pci driver
>> +	 * and internal (private) data
>> +	 */
>> +	data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);
>> +	if (data == NULL)
>> +		goto error;
>> +
>> +	pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);
>> +	if (pci_dev == NULL)
>> +		goto error;
>> +
>> +	internals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node);
>> +	if (internals == NULL)
>> +		goto error;
>> +
>> +	/* reserve an ethdev entry */
>> +	eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL);
>> +	if (eth_dev == NULL)
>> +		goto error;
>> +
>> +	/* now put it all together
>> +	 * - store queue data in internals,
>> +	 * - store numa_node info in pci_driver
>> +	 * - point eth_dev_data to internals and pci_driver
>> +	 * - and point eth_dev structure to new eth_dev_data structure
>> +	 */
>> +	/* NOTE: we'll replace the data element, of originally allocated eth_dev
>> +	 * so the nulls are local per-process */
>> +
>> +	internals->nb_rx_queues = nb_rx_queues;
>> +	internals->nb_tx_queues = nb_tx_queues;
>> +	internals->packet_size = packet_size;
>> +	internals->packet_copy = packet_copy;
>> +	internals->numa_node = numa_node;
>> +
>> +	pci_dev->numa_node = numa_node;
>> +
>> +	data->dev_private = internals;
>> +	data->port_id = eth_dev->data->port_id;
>> +	data->nb_rx_queues = (uint16_t)nb_rx_queues;
>> +	data->nb_tx_queues = (uint16_t)nb_tx_queues;
>> +	data->dev_link = pmd_link;
>> +	data->mac_addrs = &eth_addr;
>> +
>> +	eth_dev->data = data;
>> +	eth_dev->dev_ops = &ops;
>> +	eth_dev->pci_dev = pci_dev;
>> +
>> +	/* finally assign rx and tx ops */
>> +	if (packet_copy) {
>> +		eth_dev->rx_pkt_burst = eth_null_copy_rx;
>> +		eth_dev->tx_pkt_burst = eth_null_copy_tx;
>> +	} else {
>> +		eth_dev->rx_pkt_burst = eth_null_rx;
>> +		eth_dev->tx_pkt_burst = eth_null_tx;
>> +	}
>> +
>> +	return 0;
>> +
>> +error:
>> +	if (data)
>> +		rte_free(data);
>> +	if (pci_dev)
>> +		rte_free(pci_dev);
>> +	if (internals)
>> +		rte_free(internals);
>> +	return -1;
>> +}
>> +
>> +static inline int
>> +get_packet_size_arg(const char *key __rte_unused,
>> +		const char *value, void *extra_args)
>> +{
>> +	const char *a = value;
>> +	unsigned *packet_size = extra_args;
> Parameters value and  extra_args should be checked.
>
>> +
>> +	*packet_size = (unsigned)strtoul(a, NULL, 0);
>> +	if (*packet_size == UINT_MAX)
>> +		return -1;
>> +
>> +	return 0;
>> +}
>> +
>> +static inline int
>> +get_packet_copy_arg(const char *key __rte_unused,
>> +		const char *value, void *extra_args)
>> +{
>> +	const char *a = value;
>> +	unsigned *packet_copy = extra_args;
> Parameters value and  extra_args should be checked.
>
>> +
>> +	*packet_copy = (unsigned)strtoul(a, NULL, 0);
>> +	if (*packet_copy == UINT_MAX)
>> +		return -1;
>> +
>> +	return 0;
>> +}
>> +
>> +static int
>> +rte_pmd_null_devinit(const char *name, const char *params) {
>> +	unsigned numa_node;
>> +	unsigned packet_size = default_packet_size;
>> +	unsigned packet_copy = default_packet_copy;
>> +	struct rte_kvargs *kvlist;
>> +	int ret;
>> +
> Input parameters name and params should be checked.
>
>> +	RTE_LOG(INFO, PMD, "Initializing pmd_null for %s\n", name);
>> +
>> +	numa_node = rte_socket_id();
>> +
>> +	kvlist = rte_kvargs_parse(params, valid_arguments);
>> +	if (kvlist == NULL)
>> +		return -1;
>> +
>> +	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) {
>> +
>> +		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_SIZE_ARG,
>> +				&get_packet_size_arg, &packet_size);
>> +		if (ret < 0)
>> +			return -1;
>> +	}
>> +
>> +	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) {
>> +
>> +		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_COPY_ARG,
>> +				&get_packet_copy_arg, &packet_copy);
>> +		if (ret < 0)
>> +			return -1;
>> +	}
>> +
>> +	RTE_LOG(INFO, PMD, "Configure pmd_null: packet size is %d, "
>> +			"packet copy is %s\n", packet_size,
>> +			packet_copy ? "enabled" : "disabled");
>> +
>> +	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
>> +}
>> +
>> +static struct rte_driver pmd_null_drv = {
>> +	.name = "eth_null",
>> +	.type = PMD_VDEV,
>> +	.init = rte_pmd_null_devinit,
>> +};
>> +
>> +PMD_REGISTER_DRIVER(pmd_null_drv);
>> --
>> 1.9.1
> Regards,
>
> Bernard.
>

^ permalink raw reply	[flat|nested] 60+ messages in thread

* [PATCH v7 1/2] librte_pmd_null: Add Null PMD
       [not found]                       ` <1423197495-1758-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  2015-02-06  4:38                         ` [PATCH v6 2/2] librte_pmd_null: Support port hotplug function Tetsuya Mukawa
  2015-02-06 11:32                         ` [PATCH v6 1/2] librte_pmd_null: Add null PMD Iremonger, Bernard
@ 2015-02-12  2:44                         ` Tetsuya Mukawa
       [not found]                           ` <1423709078-20999-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  2 siblings, 1 reply; 60+ messages in thread
From: Tetsuya Mukawa @ 2015-02-12  2:44 UTC (permalink / raw)
  To: dev-VfR2kkLFssw

Null PMD is a driver of the virtual device particularly designed to measure
performance of DPDK PMDs. When an application call rx, Null PMD just allocates
mbufs and returns those. Also tx, the PMD just frees mbufs.

The PMD has following options.
- size: specify packe size allocated by RX. Default packet size is 64.
- copy: specify 1 or 0 to enable or disable copy while RX and TX.
	Default value is 0(disabled).
	This option is used for emulating more realistic data transfer.
	Copy size is equal to packet size.

To use the PMD, enable CONFIG_RTE_BUILD_SHARED_LIB in config file. Then
compile the PMD as shared library. The library can be linked using '-d'
option when an application invokes.

Here is an example.
$ sudo ./testpmd -c f -n 4 -d librte_pmd_null.so \
	--vdev 'eth_null0' --vdev 'eth_null1' -- -i --no-flush-rx

If testpmd is compiled with CONFIG_RTE_BUILD_SHARED_LIB, it may need to
specify more libraries using '-d' option.

v7:
 - Add parameter checkings.
   (Thanks to Iremonger, Bernard)
 - Remove needless "__rte_unused".
v4:
 - Fix memory leak.
   (Thanks to Iremonger, Bernard)

Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
---
 config/common_bsdapp               |   5 +
 config/common_linuxapp             |   5 +
 lib/Makefile                       |   1 +
 lib/librte_pmd_null/Makefile       |  58 ++++
 lib/librte_pmd_null/rte_eth_null.c | 541 +++++++++++++++++++++++++++++++++++++
 5 files changed, 610 insertions(+)
 create mode 100644 lib/librte_pmd_null/Makefile
 create mode 100644 lib/librte_pmd_null/rte_eth_null.c

diff --git a/config/common_bsdapp b/config/common_bsdapp
index 57bacb8..8b4a684 100644
--- a/config/common_bsdapp
+++ b/config/common_bsdapp
@@ -224,6 +224,11 @@ CONFIG_RTE_LIBRTE_PMD_PCAP=y
 CONFIG_RTE_LIBRTE_PMD_BOND=y
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/config/common_linuxapp b/config/common_linuxapp
index 81055f8..4ab31e8 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -237,6 +237,11 @@ CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
 CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/lib/Makefile b/lib/Makefile
index d617d81..2fc098b 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -53,6 +53,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += librte_pmd_virtio
 DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt
 DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += librte_vhost
+DIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += librte_pmd_null
 DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash
 DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm
 DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl
diff --git a/lib/librte_pmd_null/Makefile b/lib/librte_pmd_null/Makefile
new file mode 100644
index 0000000..0ec4db9
--- /dev/null
+++ b/lib/librte_pmd_null/Makefile
@@ -0,0 +1,58 @@
+#   BSD LICENSE
+#
+#   Copyright (C) IGEL Co.,Ltd.
+#   All rights reserved.
+#
+#   Redistribution and use in source and binary forms, with or without
+#   modification, are permitted provided that the following conditions
+#   are met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in
+#       the documentation and/or other materials provided with the
+#       distribution.
+#     * Neither the name of IGEL Co.,Ltd. nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_pmd_null.a
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += rte_eth_null.c
+
+#
+# Export include files
+#
+SYMLINK-y-include +=
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_malloc
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_kvargs
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
new file mode 100644
index 0000000..779db63
--- /dev/null
+++ b/lib/librte_pmd_null/rte_eth_null.c
@@ -0,0 +1,541 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright (C) IGEL Co.,Ltd.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of IGEL Co.,Ltd. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_dev.h>
+#include <rte_kvargs.h>
+
+#define ETH_NULL_PACKET_SIZE_ARG	"size"
+#define ETH_NULL_PACKET_COPY_ARG	"copy"
+
+static unsigned default_packet_size = 64;
+static unsigned default_packet_copy;
+
+static const char const *valid_arguments[] = {
+	ETH_NULL_PACKET_SIZE_ARG,
+	ETH_NULL_PACKET_COPY_ARG,
+	NULL
+};
+
+struct pmd_internals;
+
+struct null_queue {
+	struct pmd_internals *internals;
+
+	struct rte_mempool *mb_pool;
+	struct rte_mbuf *dummy_packet;
+
+	rte_atomic64_t rx_pkts;
+	rte_atomic64_t tx_pkts;
+	rte_atomic64_t err_pkts;
+};
+
+struct pmd_internals {
+	unsigned packet_size;
+	unsigned packet_copy;
+	unsigned numa_node;
+
+	unsigned nb_rx_queues;
+	unsigned nb_tx_queues;
+
+	struct null_queue rx_null_queues[1];
+	struct null_queue tx_null_queues[1];
+};
+
+
+static struct ether_addr eth_addr = { .addr_bytes = {0} };
+static const char *drivername = "Null PMD";
+static struct rte_eth_link pmd_link = {
+	.link_speed = 10000,
+	.link_duplex = ETH_LINK_FULL_DUPLEX,
+	.link_status = 0
+};
+
+static uint16_t
+eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size;
+
+	if ((q ==NULL) || (bufs == NULL))
+		return 0;
+
+	packet_size = h->internals->packet_size;
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size;
+
+	if ((q ==NULL) || (bufs == NULL))
+		return 0;
+
+	packet_size = h->internals->packet_size;
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,
+					packet_size);
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+
+	if ((q ==NULL) || (bufs == NULL))
+		return 0;
+
+	for (i = 0; i < nb_bufs; i++)
+		rte_pktmbuf_free(bufs[i]);
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	if ((q ==NULL) || (bufs == NULL))
+		return 0;
+
+	for (i = 0; i < nb_bufs; i++) {
+		rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *),
+					packet_size);
+		rte_pktmbuf_free(bufs[i]);
+	}
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static int
+eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; }
+
+static int
+eth_dev_start(struct rte_eth_dev *dev)
+{
+	if (dev == NULL)
+		return -EINVAL;
+
+	dev->data->dev_link.link_status = 1;
+	return 0;
+}
+
+static void
+eth_dev_stop(struct rte_eth_dev *dev)
+{
+	if (dev == NULL)
+		return;
+
+	dev->data->dev_link.link_status = 0;
+}
+
+static int
+eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+		uint16_t nb_rx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_rxconf *rx_conf __rte_unused,
+		struct rte_mempool *mb_pool)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals;
+	unsigned packet_size;
+
+	if ((dev == NULL) || (mb_pool == NULL))
+		return -EINVAL;
+
+	if (rx_queue_id != 0)
+		return -ENODEV;
+
+	internals = dev->data->dev_private;
+	packet_size = internals->packet_size;
+
+	internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool;
+	dev->data->rx_queues[rx_queue_id] =
+		&internals->rx_null_queues[rx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->rx_null_queues[rx_queue_id].internals = internals;
+	internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+static int
+eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+		uint16_t nb_tx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals;
+	unsigned packet_size;
+
+	if (dev == NULL)
+		return -EINVAL;
+
+	if (tx_queue_id != 0)
+		return -ENODEV;
+
+	internals = dev->data->dev_private;
+	packet_size = internals->packet_size;
+
+	dev->data->tx_queues[tx_queue_id] =
+		&internals->tx_null_queues[tx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->tx_null_queues[tx_queue_id].internals = internals;
+	internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+
+static void
+eth_dev_info(struct rte_eth_dev *dev,
+		struct rte_eth_dev_info *dev_info)
+{
+	struct pmd_internals *internals;
+
+	if ((dev == NULL) || (dev_info == NULL))
+		return;
+
+	internals = dev->data->dev_private;
+	dev_info->driver_name = drivername;
+	dev_info->max_mac_addrs = 1;
+	dev_info->max_rx_pktlen = (uint32_t)-1;
+	dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;
+	dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;
+	dev_info->min_rx_bufsize = 0;
+	dev_info->pci_dev = NULL;
+}
+
+static void
+eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)
+{
+	unsigned i;
+	unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
+	const struct pmd_internals *internal;
+
+	if ((dev == NULL) || (igb_stats == NULL))
+		return;
+
+	internal = dev->data->dev_private;
+	memset(igb_stats, 0, sizeof(*igb_stats));
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_rx_queues; i++) {
+		igb_stats->q_ipackets[i] =
+			internal->rx_null_queues[i].rx_pkts.cnt;
+		rx_total += igb_stats->q_ipackets[i];
+	}
+
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_tx_queues; i++) {
+		igb_stats->q_opackets[i] =
+			internal->tx_null_queues[i].tx_pkts.cnt;
+		igb_stats->q_errors[i] =
+			internal->tx_null_queues[i].err_pkts.cnt;
+		tx_total += igb_stats->q_opackets[i];
+		tx_err_total += igb_stats->q_errors[i];
+	}
+
+	igb_stats->ipackets = rx_total;
+	igb_stats->opackets = tx_total;
+	igb_stats->oerrors = tx_err_total;
+}
+
+static void
+eth_stats_reset(struct rte_eth_dev *dev)
+{
+	unsigned i;
+	struct pmd_internals *internal;
+
+	if (dev == NULL)
+		return;
+
+	internal = dev->data->dev_private;
+	for (i = 0; i < internal->nb_rx_queues; i++)
+		internal->rx_null_queues[i].rx_pkts.cnt = 0;
+	for (i = 0; i < internal->nb_tx_queues; i++) {
+		internal->tx_null_queues[i].tx_pkts.cnt = 0;
+		internal->tx_null_queues[i].err_pkts.cnt = 0;
+	}
+}
+
+static void
+eth_queue_release(void *q)
+{
+	struct null_queue *nq;
+
+	if (q == NULL)
+		return;
+
+	nq = q;
+	if (nq->dummy_packet)
+		rte_free(nq->dummy_packet);
+}
+
+static int
+eth_link_update(struct rte_eth_dev *dev __rte_unused,
+		int wait_to_complete __rte_unused) { return 0; }
+
+static struct eth_dev_ops ops = {
+		.dev_start = eth_dev_start,
+		.dev_stop = eth_dev_stop,
+		.dev_configure = eth_dev_configure,
+		.dev_infos_get = eth_dev_info,
+		.rx_queue_setup = eth_rx_queue_setup,
+		.tx_queue_setup = eth_tx_queue_setup,
+		.rx_queue_release = eth_queue_release,
+		.tx_queue_release = eth_queue_release,
+		.link_update = eth_link_update,
+		.stats_get = eth_stats_get,
+		.stats_reset = eth_stats_reset,
+};
+
+static int
+eth_dev_null_create(const char *name,
+		const unsigned numa_node,
+		unsigned packet_size,
+		unsigned packet_copy)
+{
+	const unsigned nb_rx_queues = 1;
+	const unsigned nb_tx_queues = 1;
+	struct rte_eth_dev_data *data = NULL;
+	struct rte_pci_device *pci_dev = NULL;
+	struct pmd_internals *internals = NULL;
+	struct rte_eth_dev *eth_dev = NULL;
+
+	if (name == NULL)
+		return -EINVAL;
+
+	RTE_LOG(INFO, PMD, "Creating null ethdev on numa socket %u\n",
+			numa_node);
+
+	/* now do all data allocation - for eth_dev structure, dummy pci driver
+	 * and internal (private) data
+	 */
+	data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);
+	if (data == NULL)
+		goto error;
+
+	pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);
+	if (pci_dev == NULL)
+		goto error;
+
+	internals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node);
+	if (internals == NULL)
+		goto error;
+
+	/* reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL);
+	if (eth_dev == NULL)
+		goto error;
+
+	/* now put it all together
+	 * - store queue data in internals,
+	 * - store numa_node info in pci_driver
+	 * - point eth_dev_data to internals and pci_driver
+	 * - and point eth_dev structure to new eth_dev_data structure
+	 */
+	/* NOTE: we'll replace the data element, of originally allocated eth_dev
+	 * so the nulls are local per-process */
+
+	internals->nb_rx_queues = nb_rx_queues;
+	internals->nb_tx_queues = nb_tx_queues;
+	internals->packet_size = packet_size;
+	internals->packet_copy = packet_copy;
+	internals->numa_node = numa_node;
+
+	pci_dev->numa_node = numa_node;
+
+	data->dev_private = internals;
+	data->port_id = eth_dev->data->port_id;
+	data->nb_rx_queues = (uint16_t)nb_rx_queues;
+	data->nb_tx_queues = (uint16_t)nb_tx_queues;
+	data->dev_link = pmd_link;
+	data->mac_addrs = &eth_addr;
+
+	eth_dev->data = data;
+	eth_dev->dev_ops = &ops;
+	eth_dev->pci_dev = pci_dev;
+
+	/* finally assign rx and tx ops */
+	if (packet_copy) {
+		eth_dev->rx_pkt_burst = eth_null_copy_rx;
+		eth_dev->tx_pkt_burst = eth_null_copy_tx;
+	} else {
+		eth_dev->rx_pkt_burst = eth_null_rx;
+		eth_dev->tx_pkt_burst = eth_null_tx;
+	}
+
+	return 0;
+
+error:
+	if (data)
+		rte_free(data);
+	if (pci_dev)
+		rte_free(pci_dev);
+	if (internals)
+		rte_free(internals);
+	return -1;
+}
+
+static inline int
+get_packet_size_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_size = extra_args;
+
+	if ((value == NULL) || (extra_args == NULL))
+		return -EINVAL;
+
+	*packet_size = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_size == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static inline int
+get_packet_copy_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_copy = extra_args;
+
+	if ((value == NULL) || (extra_args == NULL))
+		return -EINVAL;
+
+	*packet_copy = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_copy == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static int
+rte_pmd_null_devinit(const char *name, const char *params)
+{
+	unsigned numa_node;
+	unsigned packet_size = default_packet_size;
+	unsigned packet_copy = default_packet_copy;
+	struct rte_kvargs *kvlist;
+	int ret;
+
+	if ((name == NULL) || (params == NULL))
+		return -EINVAL;
+
+	RTE_LOG(INFO, PMD, "Initializing pmd_null for %s\n", name);
+
+	numa_node = rte_socket_id();
+
+	kvlist = rte_kvargs_parse(params, valid_arguments);
+	if (kvlist == NULL)
+		return -1;
+
+	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) {
+
+		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_SIZE_ARG,
+				&get_packet_size_arg, &packet_size);
+		if (ret < 0)
+			return -1;
+	}
+
+	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) {
+
+		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_COPY_ARG,
+				&get_packet_copy_arg, &packet_copy);
+		if (ret < 0)
+			return -1;
+	}
+
+	RTE_LOG(INFO, PMD, "Configure pmd_null: packet size is %d, "
+			"packet copy is %s\n", packet_size,
+			packet_copy ? "enabled" : "disabled");
+
+	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
+}
+
+static struct rte_driver pmd_null_drv = {
+	.name = "eth_null",
+	.type = PMD_VDEV,
+	.init = rte_pmd_null_devinit,
+};
+
+PMD_REGISTER_DRIVER(pmd_null_drv);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v7 2/2] librte_pmd_null: Support port hotplug function
       [not found]                           ` <1423709078-20999-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2015-02-12  2:44                             ` Tetsuya Mukawa
  2015-02-16  4:19                             ` [PATCH v8 1/2] librte_pmd_null: Add Null PMD Tetsuya Mukawa
       [not found]                             ` <1424060349-23693-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  2 siblings, 0 replies; 60+ messages in thread
From: Tetsuya Mukawa @ 2015-02-12  2:44 UTC (permalink / raw)
  To: dev-VfR2kkLFssw

This patch adds port hotplug support to Null PMD.

v7:
 - Add parameter checkings.
   (Thanks to Iremonger, Bernard)
v6:
 - Fix a parameter of rte_eth_dev_free().
v4:
 - Fix commit title.

Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
---
 lib/librte_pmd_null/rte_eth_null.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
index 779db63..1bc4ef3 100644
--- a/lib/librte_pmd_null/rte_eth_null.c
+++ b/lib/librte_pmd_null/rte_eth_null.c
@@ -336,6 +336,13 @@ eth_stats_reset(struct rte_eth_dev *dev)
 	}
 }
 
+static struct eth_driver rte_null_pmd = {
+	.pci_drv = {
+		.name = "rte_null_pmd",
+		.drv_flags = RTE_PCI_DRV_DETACHABLE,
+	},
+};
+
 static void
 eth_queue_release(void *q)
 {
@@ -429,10 +436,12 @@ eth_dev_null_create(const char *name,
 	data->nb_tx_queues = (uint16_t)nb_tx_queues;
 	data->dev_link = pmd_link;
 	data->mac_addrs = &eth_addr;
+	strncpy(data->name, eth_dev->data->name, strlen(eth_dev->data->name));
 
 	eth_dev->data = data;
 	eth_dev->dev_ops = &ops;
 	eth_dev->pci_dev = pci_dev;
+	eth_dev->driver = &rte_null_pmd;
 
 	/* finally assign rx and tx ops */
 	if (packet_copy) {
@@ -532,10 +541,36 @@ rte_pmd_null_devinit(const char *name, const char *params)
 	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
 }
 
+static int
+rte_pmd_null_devuninit(const char *name, const char *params __rte_unused)
+{
+	struct rte_eth_dev *eth_dev = NULL;
+
+	if (name == NULL)
+		return -EINVAL;
+
+	RTE_LOG(INFO, PMD, "Closing null ethdev on numa socket %u\n",
+			rte_socket_id());
+
+	/* reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocated(name);
+	if (eth_dev == NULL)
+		return -1;
+
+	rte_free(eth_dev->data->dev_private);
+	rte_free(eth_dev->data);
+	rte_free(eth_dev->pci_dev);
+
+	rte_eth_dev_free(eth_dev);
+
+	return 0;
+}
+
 static struct rte_driver pmd_null_drv = {
 	.name = "eth_null",
 	.type = PMD_VDEV,
 	.init = rte_pmd_null_devinit,
+	.uninit = rte_pmd_null_devuninit,
 };
 
 PMD_REGISTER_DRIVER(pmd_null_drv);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v8 1/2] librte_pmd_null: Add Null PMD
       [not found]                           ` <1423709078-20999-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  2015-02-12  2:44                             ` [PATCH v7 2/2] librte_pmd_null: Support port hotplug function Tetsuya Mukawa
@ 2015-02-16  4:19                             ` Tetsuya Mukawa
       [not found]                             ` <1424060349-23693-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  2 siblings, 0 replies; 60+ messages in thread
From: Tetsuya Mukawa @ 2015-02-16  4:19 UTC (permalink / raw)
  To: dev-VfR2kkLFssw

Null PMD is a driver of the virtual device particularly designed to measure
performance of DPDK PMDs. When an application call rx, Null PMD just allocates
mbufs and returns those. Also tx, the PMD just frees mbufs.

The PMD has following options.
- size: specify packe size allocated by RX. Default packet size is 64.
- copy: specify 1 or 0 to enable or disable copy while RX and TX.
	Default value is 0(disabled).
	This option is used for emulating more realistic data transfer.
	Copy size is equal to packet size.

To use the PMD, enable CONFIG_RTE_BUILD_SHARED_LIB in config file. Then
compile the PMD as shared library. The library can be linked using '-d'
option when an application invokes.

Here is an example.
$ sudo ./testpmd -c f -n 4 -d librte_pmd_null.so \
	--vdev 'eth_null0' --vdev 'eth_null1' -- -i --no-flush-rx

If testpmd is compiled with CONFIG_RTE_BUILD_SHARED_LIB, it may need to
specify more libraries using '-d' option.

v8:
 - Fix Makefile and add version map file.
   (Thanks to Qiu, Michael and Iremonger, Bernard)
v7:
 - Add parameter checkings.
   (Thanks to Iremonger, Bernard)
 - Remove needless "__rte_unused".
v4:
 - Fix memory leak.
   (Thanks to Iremonger, Bernard)

Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
---
 config/common_bsdapp                         |   5 +
 config/common_linuxapp                       |   5 +
 lib/Makefile                                 |   1 +
 lib/librte_pmd_null/Makefile                 |  62 +++
 lib/librte_pmd_null/rte_eth_null.c           | 541 +++++++++++++++++++++++++++
 lib/librte_pmd_null/rte_pmd_null_version.map |   4 +
 6 files changed, 618 insertions(+)
 create mode 100644 lib/librte_pmd_null/Makefile
 create mode 100644 lib/librte_pmd_null/rte_eth_null.c
 create mode 100644 lib/librte_pmd_null/rte_pmd_null_version.map

diff --git a/config/common_bsdapp b/config/common_bsdapp
index 57bacb8..8b4a684 100644
--- a/config/common_bsdapp
+++ b/config/common_bsdapp
@@ -224,6 +224,11 @@ CONFIG_RTE_LIBRTE_PMD_PCAP=y
 CONFIG_RTE_LIBRTE_PMD_BOND=y
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/config/common_linuxapp b/config/common_linuxapp
index 81055f8..4ab31e8 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -237,6 +237,11 @@ CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
 CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/lib/Makefile b/lib/Makefile
index d617d81..2fc098b 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -53,6 +53,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += librte_pmd_virtio
 DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt
 DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += librte_vhost
+DIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += librte_pmd_null
 DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash
 DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm
 DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl
diff --git a/lib/librte_pmd_null/Makefile b/lib/librte_pmd_null/Makefile
new file mode 100644
index 0000000..6472015
--- /dev/null
+++ b/lib/librte_pmd_null/Makefile
@@ -0,0 +1,62 @@
+#   BSD LICENSE
+#
+#   Copyright (C) IGEL Co.,Ltd.
+#   All rights reserved.
+#
+#   Redistribution and use in source and binary forms, with or without
+#   modification, are permitted provided that the following conditions
+#   are met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in
+#       the documentation and/or other materials provided with the
+#       distribution.
+#     * Neither the name of IGEL Co.,Ltd. nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_pmd_null.a
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+EXPORT_MAP := rte_pmd_null_version.map
+
+LIBABIVER := 1
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += rte_eth_null.c
+
+#
+# Export include files
+#
+SYMLINK-y-include +=
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_malloc
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_kvargs
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
new file mode 100644
index 0000000..779db63
--- /dev/null
+++ b/lib/librte_pmd_null/rte_eth_null.c
@@ -0,0 +1,541 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright (C) IGEL Co.,Ltd.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of IGEL Co.,Ltd. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_dev.h>
+#include <rte_kvargs.h>
+
+#define ETH_NULL_PACKET_SIZE_ARG	"size"
+#define ETH_NULL_PACKET_COPY_ARG	"copy"
+
+static unsigned default_packet_size = 64;
+static unsigned default_packet_copy;
+
+static const char const *valid_arguments[] = {
+	ETH_NULL_PACKET_SIZE_ARG,
+	ETH_NULL_PACKET_COPY_ARG,
+	NULL
+};
+
+struct pmd_internals;
+
+struct null_queue {
+	struct pmd_internals *internals;
+
+	struct rte_mempool *mb_pool;
+	struct rte_mbuf *dummy_packet;
+
+	rte_atomic64_t rx_pkts;
+	rte_atomic64_t tx_pkts;
+	rte_atomic64_t err_pkts;
+};
+
+struct pmd_internals {
+	unsigned packet_size;
+	unsigned packet_copy;
+	unsigned numa_node;
+
+	unsigned nb_rx_queues;
+	unsigned nb_tx_queues;
+
+	struct null_queue rx_null_queues[1];
+	struct null_queue tx_null_queues[1];
+};
+
+
+static struct ether_addr eth_addr = { .addr_bytes = {0} };
+static const char *drivername = "Null PMD";
+static struct rte_eth_link pmd_link = {
+	.link_speed = 10000,
+	.link_duplex = ETH_LINK_FULL_DUPLEX,
+	.link_status = 0
+};
+
+static uint16_t
+eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size;
+
+	if ((q ==NULL) || (bufs == NULL))
+		return 0;
+
+	packet_size = h->internals->packet_size;
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size;
+
+	if ((q ==NULL) || (bufs == NULL))
+		return 0;
+
+	packet_size = h->internals->packet_size;
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,
+					packet_size);
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+
+	if ((q ==NULL) || (bufs == NULL))
+		return 0;
+
+	for (i = 0; i < nb_bufs; i++)
+		rte_pktmbuf_free(bufs[i]);
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	if ((q ==NULL) || (bufs == NULL))
+		return 0;
+
+	for (i = 0; i < nb_bufs; i++) {
+		rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *),
+					packet_size);
+		rte_pktmbuf_free(bufs[i]);
+	}
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static int
+eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; }
+
+static int
+eth_dev_start(struct rte_eth_dev *dev)
+{
+	if (dev == NULL)
+		return -EINVAL;
+
+	dev->data->dev_link.link_status = 1;
+	return 0;
+}
+
+static void
+eth_dev_stop(struct rte_eth_dev *dev)
+{
+	if (dev == NULL)
+		return;
+
+	dev->data->dev_link.link_status = 0;
+}
+
+static int
+eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+		uint16_t nb_rx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_rxconf *rx_conf __rte_unused,
+		struct rte_mempool *mb_pool)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals;
+	unsigned packet_size;
+
+	if ((dev == NULL) || (mb_pool == NULL))
+		return -EINVAL;
+
+	if (rx_queue_id != 0)
+		return -ENODEV;
+
+	internals = dev->data->dev_private;
+	packet_size = internals->packet_size;
+
+	internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool;
+	dev->data->rx_queues[rx_queue_id] =
+		&internals->rx_null_queues[rx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->rx_null_queues[rx_queue_id].internals = internals;
+	internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+static int
+eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+		uint16_t nb_tx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals;
+	unsigned packet_size;
+
+	if (dev == NULL)
+		return -EINVAL;
+
+	if (tx_queue_id != 0)
+		return -ENODEV;
+
+	internals = dev->data->dev_private;
+	packet_size = internals->packet_size;
+
+	dev->data->tx_queues[tx_queue_id] =
+		&internals->tx_null_queues[tx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->tx_null_queues[tx_queue_id].internals = internals;
+	internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+
+static void
+eth_dev_info(struct rte_eth_dev *dev,
+		struct rte_eth_dev_info *dev_info)
+{
+	struct pmd_internals *internals;
+
+	if ((dev == NULL) || (dev_info == NULL))
+		return;
+
+	internals = dev->data->dev_private;
+	dev_info->driver_name = drivername;
+	dev_info->max_mac_addrs = 1;
+	dev_info->max_rx_pktlen = (uint32_t)-1;
+	dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;
+	dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;
+	dev_info->min_rx_bufsize = 0;
+	dev_info->pci_dev = NULL;
+}
+
+static void
+eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)
+{
+	unsigned i;
+	unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
+	const struct pmd_internals *internal;
+
+	if ((dev == NULL) || (igb_stats == NULL))
+		return;
+
+	internal = dev->data->dev_private;
+	memset(igb_stats, 0, sizeof(*igb_stats));
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_rx_queues; i++) {
+		igb_stats->q_ipackets[i] =
+			internal->rx_null_queues[i].rx_pkts.cnt;
+		rx_total += igb_stats->q_ipackets[i];
+	}
+
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_tx_queues; i++) {
+		igb_stats->q_opackets[i] =
+			internal->tx_null_queues[i].tx_pkts.cnt;
+		igb_stats->q_errors[i] =
+			internal->tx_null_queues[i].err_pkts.cnt;
+		tx_total += igb_stats->q_opackets[i];
+		tx_err_total += igb_stats->q_errors[i];
+	}
+
+	igb_stats->ipackets = rx_total;
+	igb_stats->opackets = tx_total;
+	igb_stats->oerrors = tx_err_total;
+}
+
+static void
+eth_stats_reset(struct rte_eth_dev *dev)
+{
+	unsigned i;
+	struct pmd_internals *internal;
+
+	if (dev == NULL)
+		return;
+
+	internal = dev->data->dev_private;
+	for (i = 0; i < internal->nb_rx_queues; i++)
+		internal->rx_null_queues[i].rx_pkts.cnt = 0;
+	for (i = 0; i < internal->nb_tx_queues; i++) {
+		internal->tx_null_queues[i].tx_pkts.cnt = 0;
+		internal->tx_null_queues[i].err_pkts.cnt = 0;
+	}
+}
+
+static void
+eth_queue_release(void *q)
+{
+	struct null_queue *nq;
+
+	if (q == NULL)
+		return;
+
+	nq = q;
+	if (nq->dummy_packet)
+		rte_free(nq->dummy_packet);
+}
+
+static int
+eth_link_update(struct rte_eth_dev *dev __rte_unused,
+		int wait_to_complete __rte_unused) { return 0; }
+
+static struct eth_dev_ops ops = {
+		.dev_start = eth_dev_start,
+		.dev_stop = eth_dev_stop,
+		.dev_configure = eth_dev_configure,
+		.dev_infos_get = eth_dev_info,
+		.rx_queue_setup = eth_rx_queue_setup,
+		.tx_queue_setup = eth_tx_queue_setup,
+		.rx_queue_release = eth_queue_release,
+		.tx_queue_release = eth_queue_release,
+		.link_update = eth_link_update,
+		.stats_get = eth_stats_get,
+		.stats_reset = eth_stats_reset,
+};
+
+static int
+eth_dev_null_create(const char *name,
+		const unsigned numa_node,
+		unsigned packet_size,
+		unsigned packet_copy)
+{
+	const unsigned nb_rx_queues = 1;
+	const unsigned nb_tx_queues = 1;
+	struct rte_eth_dev_data *data = NULL;
+	struct rte_pci_device *pci_dev = NULL;
+	struct pmd_internals *internals = NULL;
+	struct rte_eth_dev *eth_dev = NULL;
+
+	if (name == NULL)
+		return -EINVAL;
+
+	RTE_LOG(INFO, PMD, "Creating null ethdev on numa socket %u\n",
+			numa_node);
+
+	/* now do all data allocation - for eth_dev structure, dummy pci driver
+	 * and internal (private) data
+	 */
+	data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);
+	if (data == NULL)
+		goto error;
+
+	pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);
+	if (pci_dev == NULL)
+		goto error;
+
+	internals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node);
+	if (internals == NULL)
+		goto error;
+
+	/* reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL);
+	if (eth_dev == NULL)
+		goto error;
+
+	/* now put it all together
+	 * - store queue data in internals,
+	 * - store numa_node info in pci_driver
+	 * - point eth_dev_data to internals and pci_driver
+	 * - and point eth_dev structure to new eth_dev_data structure
+	 */
+	/* NOTE: we'll replace the data element, of originally allocated eth_dev
+	 * so the nulls are local per-process */
+
+	internals->nb_rx_queues = nb_rx_queues;
+	internals->nb_tx_queues = nb_tx_queues;
+	internals->packet_size = packet_size;
+	internals->packet_copy = packet_copy;
+	internals->numa_node = numa_node;
+
+	pci_dev->numa_node = numa_node;
+
+	data->dev_private = internals;
+	data->port_id = eth_dev->data->port_id;
+	data->nb_rx_queues = (uint16_t)nb_rx_queues;
+	data->nb_tx_queues = (uint16_t)nb_tx_queues;
+	data->dev_link = pmd_link;
+	data->mac_addrs = &eth_addr;
+
+	eth_dev->data = data;
+	eth_dev->dev_ops = &ops;
+	eth_dev->pci_dev = pci_dev;
+
+	/* finally assign rx and tx ops */
+	if (packet_copy) {
+		eth_dev->rx_pkt_burst = eth_null_copy_rx;
+		eth_dev->tx_pkt_burst = eth_null_copy_tx;
+	} else {
+		eth_dev->rx_pkt_burst = eth_null_rx;
+		eth_dev->tx_pkt_burst = eth_null_tx;
+	}
+
+	return 0;
+
+error:
+	if (data)
+		rte_free(data);
+	if (pci_dev)
+		rte_free(pci_dev);
+	if (internals)
+		rte_free(internals);
+	return -1;
+}
+
+static inline int
+get_packet_size_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_size = extra_args;
+
+	if ((value == NULL) || (extra_args == NULL))
+		return -EINVAL;
+
+	*packet_size = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_size == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static inline int
+get_packet_copy_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_copy = extra_args;
+
+	if ((value == NULL) || (extra_args == NULL))
+		return -EINVAL;
+
+	*packet_copy = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_copy == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static int
+rte_pmd_null_devinit(const char *name, const char *params)
+{
+	unsigned numa_node;
+	unsigned packet_size = default_packet_size;
+	unsigned packet_copy = default_packet_copy;
+	struct rte_kvargs *kvlist;
+	int ret;
+
+	if ((name == NULL) || (params == NULL))
+		return -EINVAL;
+
+	RTE_LOG(INFO, PMD, "Initializing pmd_null for %s\n", name);
+
+	numa_node = rte_socket_id();
+
+	kvlist = rte_kvargs_parse(params, valid_arguments);
+	if (kvlist == NULL)
+		return -1;
+
+	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) {
+
+		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_SIZE_ARG,
+				&get_packet_size_arg, &packet_size);
+		if (ret < 0)
+			return -1;
+	}
+
+	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) {
+
+		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_COPY_ARG,
+				&get_packet_copy_arg, &packet_copy);
+		if (ret < 0)
+			return -1;
+	}
+
+	RTE_LOG(INFO, PMD, "Configure pmd_null: packet size is %d, "
+			"packet copy is %s\n", packet_size,
+			packet_copy ? "enabled" : "disabled");
+
+	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
+}
+
+static struct rte_driver pmd_null_drv = {
+	.name = "eth_null",
+	.type = PMD_VDEV,
+	.init = rte_pmd_null_devinit,
+};
+
+PMD_REGISTER_DRIVER(pmd_null_drv);
diff --git a/lib/librte_pmd_null/rte_pmd_null_version.map b/lib/librte_pmd_null/rte_pmd_null_version.map
new file mode 100644
index 0000000..ef35398
--- /dev/null
+++ b/lib/librte_pmd_null/rte_pmd_null_version.map
@@ -0,0 +1,4 @@
+DPDK_2.0 {
+
+	local: *;
+};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v8 2/2] librte_pmd_null: Support port hotplug function
       [not found]                             ` <1424060349-23693-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2015-02-16  4:19                               ` Tetsuya Mukawa
       [not found]                                 ` <1424060349-23693-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  2015-02-16 16:38                               ` [PATCH v8 1/2] librte_pmd_null: Add Null PMD Iremonger, Bernard
  2015-02-19 10:41                               ` [PATCH v9 " Tetsuya Mukawa
  2 siblings, 1 reply; 60+ messages in thread
From: Tetsuya Mukawa @ 2015-02-16  4:19 UTC (permalink / raw)
  To: dev-VfR2kkLFssw

This patch adds port hotplug support to Null PMD.

v7:
 - Add parameter checkings.
   (Thanks to Iremonger, Bernard)
v6:
 - Fix a parameter of rte_eth_dev_free().
v4:
 - Fix commit title.

Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
---
 lib/librte_pmd_null/rte_eth_null.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
index 779db63..1bc4ef3 100644
--- a/lib/librte_pmd_null/rte_eth_null.c
+++ b/lib/librte_pmd_null/rte_eth_null.c
@@ -336,6 +336,13 @@ eth_stats_reset(struct rte_eth_dev *dev)
 	}
 }
 
+static struct eth_driver rte_null_pmd = {
+	.pci_drv = {
+		.name = "rte_null_pmd",
+		.drv_flags = RTE_PCI_DRV_DETACHABLE,
+	},
+};
+
 static void
 eth_queue_release(void *q)
 {
@@ -429,10 +436,12 @@ eth_dev_null_create(const char *name,
 	data->nb_tx_queues = (uint16_t)nb_tx_queues;
 	data->dev_link = pmd_link;
 	data->mac_addrs = &eth_addr;
+	strncpy(data->name, eth_dev->data->name, strlen(eth_dev->data->name));
 
 	eth_dev->data = data;
 	eth_dev->dev_ops = &ops;
 	eth_dev->pci_dev = pci_dev;
+	eth_dev->driver = &rte_null_pmd;
 
 	/* finally assign rx and tx ops */
 	if (packet_copy) {
@@ -532,10 +541,36 @@ rte_pmd_null_devinit(const char *name, const char *params)
 	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
 }
 
+static int
+rte_pmd_null_devuninit(const char *name, const char *params __rte_unused)
+{
+	struct rte_eth_dev *eth_dev = NULL;
+
+	if (name == NULL)
+		return -EINVAL;
+
+	RTE_LOG(INFO, PMD, "Closing null ethdev on numa socket %u\n",
+			rte_socket_id());
+
+	/* reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocated(name);
+	if (eth_dev == NULL)
+		return -1;
+
+	rte_free(eth_dev->data->dev_private);
+	rte_free(eth_dev->data);
+	rte_free(eth_dev->pci_dev);
+
+	rte_eth_dev_free(eth_dev);
+
+	return 0;
+}
+
 static struct rte_driver pmd_null_drv = {
 	.name = "eth_null",
 	.type = PMD_VDEV,
 	.init = rte_pmd_null_devinit,
+	.uninit = rte_pmd_null_devuninit,
 };
 
 PMD_REGISTER_DRIVER(pmd_null_drv);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 1/2] librte_pmd_null: Add Null PMD
       [not found]                             ` <1424060349-23693-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  2015-02-16  4:19                               ` [PATCH v8 2/2] librte_pmd_null: Support port hotplug function Tetsuya Mukawa
@ 2015-02-16 16:38                               ` Iremonger, Bernard
  2015-02-19 10:41                               ` [PATCH v9 " Tetsuya Mukawa
  2 siblings, 0 replies; 60+ messages in thread
From: Iremonger, Bernard @ 2015-02-16 16:38 UTC (permalink / raw)
  To: Tetsuya Mukawa, dev-VfR2kkLFssw

> -----Original Message-----
> From: Tetsuya Mukawa [mailto:mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org]
> Sent: Monday, February 16, 2015 4:19 AM
> To: dev-VfR2kkLFssw@public.gmane.org
> Cc: Qiu, Michael; Iremonger, Bernard; Tetsuya Mukawa
> Subject: [PATCH v8 1/2] librte_pmd_null: Add Null PMD
> 
> Null PMD is a driver of the virtual device particularly designed to measure performance of DPDK PMDs.
> When an application call rx, Null PMD just allocates mbufs and returns those. Also tx, the PMD just
> frees mbufs.
> 
> The PMD has following options.
> - size: specify packe size allocated by RX. Default packet size is 64.
> - copy: specify 1 or 0 to enable or disable copy while RX and TX.
> 	Default value is 0(disabled).
> 	This option is used for emulating more realistic data transfer.
> 	Copy size is equal to packet size.
> 
> To use the PMD, enable CONFIG_RTE_BUILD_SHARED_LIB in config file. Then compile the PMD as
> shared library. The library can be linked using '-d'
> option when an application invokes.
> 
> Here is an example.
> $ sudo ./testpmd -c f -n 4 -d librte_pmd_null.so \
> 	--vdev 'eth_null0' --vdev 'eth_null1' -- -i --no-flush-rx
> 
> If testpmd is compiled with CONFIG_RTE_BUILD_SHARED_LIB, it may need to specify more libraries
> using '-d' option.
> 
> v8:
>  - Fix Makefile and add version map file.
>    (Thanks to Qiu, Michael and Iremonger, Bernard)
> v7:
>  - Add parameter checkings.
>    (Thanks to Iremonger, Bernard)
>  - Remove needless "__rte_unused".
> v4:
>  - Fix memory leak.
>    (Thanks to Iremonger, Bernard)
> 
> Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>

Acked-by: Bernard Iremonger <bernard.iremonger-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 2/2] librte_pmd_null: Support port hotplug function
       [not found]                                 ` <1424060349-23693-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2015-02-16 16:38                                   ` Iremonger, Bernard
  0 siblings, 0 replies; 60+ messages in thread
From: Iremonger, Bernard @ 2015-02-16 16:38 UTC (permalink / raw)
  To: Tetsuya Mukawa, dev-VfR2kkLFssw

> -----Original Message-----
> From: Tetsuya Mukawa [mailto:mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org]
> Sent: Monday, February 16, 2015 4:19 AM
> To: dev-VfR2kkLFssw@public.gmane.org
> Cc: Qiu, Michael; Iremonger, Bernard; Tetsuya Mukawa
> Subject: [PATCH v8 2/2] librte_pmd_null: Support port hotplug function
> 
> This patch adds port hotplug support to Null PMD.
> 
> v7:
>  - Add parameter checkings.
>    (Thanks to Iremonger, Bernard)
> v6:
>  - Fix a parameter of rte_eth_dev_free().
> v4:
>  - Fix commit title.
> 
> Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>

Acked-by: Bernard Iremonger <bernard.iremonger-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

^ permalink raw reply	[flat|nested] 60+ messages in thread

* [PATCH v9 1/2] librte_pmd_null: Add Null PMD
       [not found]                             ` <1424060349-23693-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  2015-02-16  4:19                               ` [PATCH v8 2/2] librte_pmd_null: Support port hotplug function Tetsuya Mukawa
  2015-02-16 16:38                               ` [PATCH v8 1/2] librte_pmd_null: Add Null PMD Iremonger, Bernard
@ 2015-02-19 10:41                               ` Tetsuya Mukawa
       [not found]                                 ` <1424342510-1107-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  2 siblings, 1 reply; 60+ messages in thread
From: Tetsuya Mukawa @ 2015-02-19 10:41 UTC (permalink / raw)
  To: dev-VfR2kkLFssw

Null PMD is a driver of the virtual device particularly designed to measure
performance of DPDK PMDs. When an application call rx, Null PMD just allocates
mbufs and returns those. Also tx, the PMD just frees mbufs.

The PMD has following options.
- size: specify packe size allocated by RX. Default packet size is 64.
- copy: specify 1 or 0 to enable or disable copy while RX and TX.
	Default value is 0(disabled).
	This option is used for emulating more realistic data transfer.
	Copy size is equal to packet size.

To use the PMD, enable CONFIG_RTE_BUILD_SHARED_LIB in config file. Then
compile the PMD as shared library. The library can be linked using '-d'
option when an application invokes.

Here is an example.
$ sudo ./testpmd -c f -n 4 -d librte_pmd_null.so \
	--vdev 'eth_null0' --vdev 'eth_null1' -- -i --no-flush-rx

If testpmd is compiled with CONFIG_RTE_BUILD_SHARED_LIB, it may need to
specify more libraries using '-d' option.

v8:
 - Fix Makefile and add version map file.
   (Thanks to Qiu, Michael and Iremonger, Bernard)
v7:
 - Add parameter checkings.
   (Thanks to Iremonger, Bernard)
 - Remove needless "__rte_unused".
v4:
 - Fix memory leak.
   (Thanks to Iremonger, Bernard)

Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
---
 config/common_bsdapp                         |   5 +
 config/common_linuxapp                       |   5 +
 lib/Makefile                                 |   1 +
 lib/librte_pmd_null/Makefile                 |  62 +++
 lib/librte_pmd_null/rte_eth_null.c           | 541 +++++++++++++++++++++++++++
 lib/librte_pmd_null/rte_pmd_null_version.map |   4 +
 6 files changed, 618 insertions(+)
 create mode 100644 lib/librte_pmd_null/Makefile
 create mode 100644 lib/librte_pmd_null/rte_eth_null.c
 create mode 100644 lib/librte_pmd_null/rte_pmd_null_version.map

diff --git a/config/common_bsdapp b/config/common_bsdapp
index e9d07e4..d019edb 100644
--- a/config/common_bsdapp
+++ b/config/common_bsdapp
@@ -241,6 +241,11 @@ CONFIG_RTE_LIBRTE_PMD_PCAP=y
 CONFIG_RTE_LIBRTE_PMD_BOND=y
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/config/common_linuxapp b/config/common_linuxapp
index 5f7fe28..ed749f2 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -248,6 +248,11 @@ CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
 CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/lib/Makefile b/lib/Makefile
index 6575a4e..5fcbb3c 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -54,6 +54,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += librte_pmd_virtio
 DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt
 DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += librte_vhost
+DIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += librte_pmd_null
 DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash
 DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm
 DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl
diff --git a/lib/librte_pmd_null/Makefile b/lib/librte_pmd_null/Makefile
new file mode 100644
index 0000000..6472015
--- /dev/null
+++ b/lib/librte_pmd_null/Makefile
@@ -0,0 +1,62 @@
+#   BSD LICENSE
+#
+#   Copyright (C) IGEL Co.,Ltd.
+#   All rights reserved.
+#
+#   Redistribution and use in source and binary forms, with or without
+#   modification, are permitted provided that the following conditions
+#   are met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in
+#       the documentation and/or other materials provided with the
+#       distribution.
+#     * Neither the name of IGEL Co.,Ltd. nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_pmd_null.a
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+EXPORT_MAP := rte_pmd_null_version.map
+
+LIBABIVER := 1
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += rte_eth_null.c
+
+#
+# Export include files
+#
+SYMLINK-y-include +=
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_malloc
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_kvargs
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
new file mode 100644
index 0000000..779db63
--- /dev/null
+++ b/lib/librte_pmd_null/rte_eth_null.c
@@ -0,0 +1,541 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright (C) IGEL Co.,Ltd.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of IGEL Co.,Ltd. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_dev.h>
+#include <rte_kvargs.h>
+
+#define ETH_NULL_PACKET_SIZE_ARG	"size"
+#define ETH_NULL_PACKET_COPY_ARG	"copy"
+
+static unsigned default_packet_size = 64;
+static unsigned default_packet_copy;
+
+static const char const *valid_arguments[] = {
+	ETH_NULL_PACKET_SIZE_ARG,
+	ETH_NULL_PACKET_COPY_ARG,
+	NULL
+};
+
+struct pmd_internals;
+
+struct null_queue {
+	struct pmd_internals *internals;
+
+	struct rte_mempool *mb_pool;
+	struct rte_mbuf *dummy_packet;
+
+	rte_atomic64_t rx_pkts;
+	rte_atomic64_t tx_pkts;
+	rte_atomic64_t err_pkts;
+};
+
+struct pmd_internals {
+	unsigned packet_size;
+	unsigned packet_copy;
+	unsigned numa_node;
+
+	unsigned nb_rx_queues;
+	unsigned nb_tx_queues;
+
+	struct null_queue rx_null_queues[1];
+	struct null_queue tx_null_queues[1];
+};
+
+
+static struct ether_addr eth_addr = { .addr_bytes = {0} };
+static const char *drivername = "Null PMD";
+static struct rte_eth_link pmd_link = {
+	.link_speed = 10000,
+	.link_duplex = ETH_LINK_FULL_DUPLEX,
+	.link_status = 0
+};
+
+static uint16_t
+eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size;
+
+	if ((q ==NULL) || (bufs == NULL))
+		return 0;
+
+	packet_size = h->internals->packet_size;
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size;
+
+	if ((q ==NULL) || (bufs == NULL))
+		return 0;
+
+	packet_size = h->internals->packet_size;
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,
+					packet_size);
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+
+	if ((q ==NULL) || (bufs == NULL))
+		return 0;
+
+	for (i = 0; i < nb_bufs; i++)
+		rte_pktmbuf_free(bufs[i]);
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	if ((q ==NULL) || (bufs == NULL))
+		return 0;
+
+	for (i = 0; i < nb_bufs; i++) {
+		rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *),
+					packet_size);
+		rte_pktmbuf_free(bufs[i]);
+	}
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static int
+eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; }
+
+static int
+eth_dev_start(struct rte_eth_dev *dev)
+{
+	if (dev == NULL)
+		return -EINVAL;
+
+	dev->data->dev_link.link_status = 1;
+	return 0;
+}
+
+static void
+eth_dev_stop(struct rte_eth_dev *dev)
+{
+	if (dev == NULL)
+		return;
+
+	dev->data->dev_link.link_status = 0;
+}
+
+static int
+eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+		uint16_t nb_rx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_rxconf *rx_conf __rte_unused,
+		struct rte_mempool *mb_pool)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals;
+	unsigned packet_size;
+
+	if ((dev == NULL) || (mb_pool == NULL))
+		return -EINVAL;
+
+	if (rx_queue_id != 0)
+		return -ENODEV;
+
+	internals = dev->data->dev_private;
+	packet_size = internals->packet_size;
+
+	internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool;
+	dev->data->rx_queues[rx_queue_id] =
+		&internals->rx_null_queues[rx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->rx_null_queues[rx_queue_id].internals = internals;
+	internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+static int
+eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+		uint16_t nb_tx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals;
+	unsigned packet_size;
+
+	if (dev == NULL)
+		return -EINVAL;
+
+	if (tx_queue_id != 0)
+		return -ENODEV;
+
+	internals = dev->data->dev_private;
+	packet_size = internals->packet_size;
+
+	dev->data->tx_queues[tx_queue_id] =
+		&internals->tx_null_queues[tx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->tx_null_queues[tx_queue_id].internals = internals;
+	internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+
+static void
+eth_dev_info(struct rte_eth_dev *dev,
+		struct rte_eth_dev_info *dev_info)
+{
+	struct pmd_internals *internals;
+
+	if ((dev == NULL) || (dev_info == NULL))
+		return;
+
+	internals = dev->data->dev_private;
+	dev_info->driver_name = drivername;
+	dev_info->max_mac_addrs = 1;
+	dev_info->max_rx_pktlen = (uint32_t)-1;
+	dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;
+	dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;
+	dev_info->min_rx_bufsize = 0;
+	dev_info->pci_dev = NULL;
+}
+
+static void
+eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)
+{
+	unsigned i;
+	unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
+	const struct pmd_internals *internal;
+
+	if ((dev == NULL) || (igb_stats == NULL))
+		return;
+
+	internal = dev->data->dev_private;
+	memset(igb_stats, 0, sizeof(*igb_stats));
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_rx_queues; i++) {
+		igb_stats->q_ipackets[i] =
+			internal->rx_null_queues[i].rx_pkts.cnt;
+		rx_total += igb_stats->q_ipackets[i];
+	}
+
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_tx_queues; i++) {
+		igb_stats->q_opackets[i] =
+			internal->tx_null_queues[i].tx_pkts.cnt;
+		igb_stats->q_errors[i] =
+			internal->tx_null_queues[i].err_pkts.cnt;
+		tx_total += igb_stats->q_opackets[i];
+		tx_err_total += igb_stats->q_errors[i];
+	}
+
+	igb_stats->ipackets = rx_total;
+	igb_stats->opackets = tx_total;
+	igb_stats->oerrors = tx_err_total;
+}
+
+static void
+eth_stats_reset(struct rte_eth_dev *dev)
+{
+	unsigned i;
+	struct pmd_internals *internal;
+
+	if (dev == NULL)
+		return;
+
+	internal = dev->data->dev_private;
+	for (i = 0; i < internal->nb_rx_queues; i++)
+		internal->rx_null_queues[i].rx_pkts.cnt = 0;
+	for (i = 0; i < internal->nb_tx_queues; i++) {
+		internal->tx_null_queues[i].tx_pkts.cnt = 0;
+		internal->tx_null_queues[i].err_pkts.cnt = 0;
+	}
+}
+
+static void
+eth_queue_release(void *q)
+{
+	struct null_queue *nq;
+
+	if (q == NULL)
+		return;
+
+	nq = q;
+	if (nq->dummy_packet)
+		rte_free(nq->dummy_packet);
+}
+
+static int
+eth_link_update(struct rte_eth_dev *dev __rte_unused,
+		int wait_to_complete __rte_unused) { return 0; }
+
+static struct eth_dev_ops ops = {
+		.dev_start = eth_dev_start,
+		.dev_stop = eth_dev_stop,
+		.dev_configure = eth_dev_configure,
+		.dev_infos_get = eth_dev_info,
+		.rx_queue_setup = eth_rx_queue_setup,
+		.tx_queue_setup = eth_tx_queue_setup,
+		.rx_queue_release = eth_queue_release,
+		.tx_queue_release = eth_queue_release,
+		.link_update = eth_link_update,
+		.stats_get = eth_stats_get,
+		.stats_reset = eth_stats_reset,
+};
+
+static int
+eth_dev_null_create(const char *name,
+		const unsigned numa_node,
+		unsigned packet_size,
+		unsigned packet_copy)
+{
+	const unsigned nb_rx_queues = 1;
+	const unsigned nb_tx_queues = 1;
+	struct rte_eth_dev_data *data = NULL;
+	struct rte_pci_device *pci_dev = NULL;
+	struct pmd_internals *internals = NULL;
+	struct rte_eth_dev *eth_dev = NULL;
+
+	if (name == NULL)
+		return -EINVAL;
+
+	RTE_LOG(INFO, PMD, "Creating null ethdev on numa socket %u\n",
+			numa_node);
+
+	/* now do all data allocation - for eth_dev structure, dummy pci driver
+	 * and internal (private) data
+	 */
+	data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);
+	if (data == NULL)
+		goto error;
+
+	pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);
+	if (pci_dev == NULL)
+		goto error;
+
+	internals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node);
+	if (internals == NULL)
+		goto error;
+
+	/* reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL);
+	if (eth_dev == NULL)
+		goto error;
+
+	/* now put it all together
+	 * - store queue data in internals,
+	 * - store numa_node info in pci_driver
+	 * - point eth_dev_data to internals and pci_driver
+	 * - and point eth_dev structure to new eth_dev_data structure
+	 */
+	/* NOTE: we'll replace the data element, of originally allocated eth_dev
+	 * so the nulls are local per-process */
+
+	internals->nb_rx_queues = nb_rx_queues;
+	internals->nb_tx_queues = nb_tx_queues;
+	internals->packet_size = packet_size;
+	internals->packet_copy = packet_copy;
+	internals->numa_node = numa_node;
+
+	pci_dev->numa_node = numa_node;
+
+	data->dev_private = internals;
+	data->port_id = eth_dev->data->port_id;
+	data->nb_rx_queues = (uint16_t)nb_rx_queues;
+	data->nb_tx_queues = (uint16_t)nb_tx_queues;
+	data->dev_link = pmd_link;
+	data->mac_addrs = &eth_addr;
+
+	eth_dev->data = data;
+	eth_dev->dev_ops = &ops;
+	eth_dev->pci_dev = pci_dev;
+
+	/* finally assign rx and tx ops */
+	if (packet_copy) {
+		eth_dev->rx_pkt_burst = eth_null_copy_rx;
+		eth_dev->tx_pkt_burst = eth_null_copy_tx;
+	} else {
+		eth_dev->rx_pkt_burst = eth_null_rx;
+		eth_dev->tx_pkt_burst = eth_null_tx;
+	}
+
+	return 0;
+
+error:
+	if (data)
+		rte_free(data);
+	if (pci_dev)
+		rte_free(pci_dev);
+	if (internals)
+		rte_free(internals);
+	return -1;
+}
+
+static inline int
+get_packet_size_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_size = extra_args;
+
+	if ((value == NULL) || (extra_args == NULL))
+		return -EINVAL;
+
+	*packet_size = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_size == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static inline int
+get_packet_copy_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_copy = extra_args;
+
+	if ((value == NULL) || (extra_args == NULL))
+		return -EINVAL;
+
+	*packet_copy = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_copy == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static int
+rte_pmd_null_devinit(const char *name, const char *params)
+{
+	unsigned numa_node;
+	unsigned packet_size = default_packet_size;
+	unsigned packet_copy = default_packet_copy;
+	struct rte_kvargs *kvlist;
+	int ret;
+
+	if ((name == NULL) || (params == NULL))
+		return -EINVAL;
+
+	RTE_LOG(INFO, PMD, "Initializing pmd_null for %s\n", name);
+
+	numa_node = rte_socket_id();
+
+	kvlist = rte_kvargs_parse(params, valid_arguments);
+	if (kvlist == NULL)
+		return -1;
+
+	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) {
+
+		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_SIZE_ARG,
+				&get_packet_size_arg, &packet_size);
+		if (ret < 0)
+			return -1;
+	}
+
+	if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) {
+
+		ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_COPY_ARG,
+				&get_packet_copy_arg, &packet_copy);
+		if (ret < 0)
+			return -1;
+	}
+
+	RTE_LOG(INFO, PMD, "Configure pmd_null: packet size is %d, "
+			"packet copy is %s\n", packet_size,
+			packet_copy ? "enabled" : "disabled");
+
+	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
+}
+
+static struct rte_driver pmd_null_drv = {
+	.name = "eth_null",
+	.type = PMD_VDEV,
+	.init = rte_pmd_null_devinit,
+};
+
+PMD_REGISTER_DRIVER(pmd_null_drv);
diff --git a/lib/librte_pmd_null/rte_pmd_null_version.map b/lib/librte_pmd_null/rte_pmd_null_version.map
new file mode 100644
index 0000000..ef35398
--- /dev/null
+++ b/lib/librte_pmd_null/rte_pmd_null_version.map
@@ -0,0 +1,4 @@
+DPDK_2.0 {
+
+	local: *;
+};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v9 2/2] librte_pmd_null: Support port hotplug function
       [not found]                                 ` <1424342510-1107-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2015-02-19 10:41                                   ` Tetsuya Mukawa
  2015-02-20  6:41                                   ` [PATCH v10 1/2] librte_pmd_null: Add Null PMD Tetsuya Mukawa
  1 sibling, 0 replies; 60+ messages in thread
From: Tetsuya Mukawa @ 2015-02-19 10:41 UTC (permalink / raw)
  To: dev-VfR2kkLFssw

This patch adds port hotplug support to Null PMD.

v9:
 - Use rte_eth_dev_release_port() instead of rte_eth_dev_free().
v7:
 - Add parameter checkings.
   (Thanks to Iremonger, Bernard)
v6:
 - Fix a parameter of rte_eth_dev_free().
v4:
 - Fix commit title.

Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
---
 lib/librte_pmd_null/rte_eth_null.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
index 779db63..5cf40f4 100644
--- a/lib/librte_pmd_null/rte_eth_null.c
+++ b/lib/librte_pmd_null/rte_eth_null.c
@@ -336,6 +336,13 @@ eth_stats_reset(struct rte_eth_dev *dev)
 	}
 }
 
+static struct eth_driver rte_null_pmd = {
+	.pci_drv = {
+		.name = "rte_null_pmd",
+		.drv_flags = RTE_PCI_DRV_DETACHABLE,
+	},
+};
+
 static void
 eth_queue_release(void *q)
 {
@@ -429,10 +436,12 @@ eth_dev_null_create(const char *name,
 	data->nb_tx_queues = (uint16_t)nb_tx_queues;
 	data->dev_link = pmd_link;
 	data->mac_addrs = &eth_addr;
+	strncpy(data->name, eth_dev->data->name, strlen(eth_dev->data->name));
 
 	eth_dev->data = data;
 	eth_dev->dev_ops = &ops;
 	eth_dev->pci_dev = pci_dev;
+	eth_dev->driver = &rte_null_pmd;
 
 	/* finally assign rx and tx ops */
 	if (packet_copy) {
@@ -532,10 +541,36 @@ rte_pmd_null_devinit(const char *name, const char *params)
 	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
 }
 
+static int
+rte_pmd_null_devuninit(const char *name)
+{
+	struct rte_eth_dev *eth_dev = NULL;
+
+	if (name == NULL)
+		return -EINVAL;
+
+	RTE_LOG(INFO, PMD, "Closing null ethdev on numa socket %u\n",
+			rte_socket_id());
+
+	/* reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocated(name);
+	if (eth_dev == NULL)
+		return -1;
+
+	rte_free(eth_dev->data->dev_private);
+	rte_free(eth_dev->data);
+	rte_free(eth_dev->pci_dev);
+
+	rte_eth_dev_release_port(eth_dev);
+
+	return 0;
+}
+
 static struct rte_driver pmd_null_drv = {
 	.name = "eth_null",
 	.type = PMD_VDEV,
 	.init = rte_pmd_null_devinit,
+	.uninit = rte_pmd_null_devuninit,
 };
 
 PMD_REGISTER_DRIVER(pmd_null_drv);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v10 1/2] librte_pmd_null: Add Null PMD
       [not found]                                 ` <1424342510-1107-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  2015-02-19 10:41                                   ` [PATCH v9 2/2] librte_pmd_null: Support port hotplug function Tetsuya Mukawa
@ 2015-02-20  6:41                                   ` Tetsuya Mukawa
       [not found]                                     ` <1424414516-18609-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  1 sibling, 1 reply; 60+ messages in thread
From: Tetsuya Mukawa @ 2015-02-20  6:41 UTC (permalink / raw)
  To: dev-VfR2kkLFssw

Null PMD is a driver of the virtual device particularly designed to measure
performance of DPDK PMDs. When an application call rx, Null PMD just allocates
mbufs and returns those. Also tx, the PMD just frees mbufs.

The PMD has following options.
- size: specify packe size allocated by RX. Default packet size is 64.
- copy: specify 1 or 0 to enable or disable copy while RX and TX.
	Default value is 0(disabled).
	This option is used for emulating more realistic data transfer.
	Copy size is equal to packet size.

To use the PMD, enable CONFIG_RTE_BUILD_SHARED_LIB in config file. Then
compile the PMD as shared library. The library can be linked using '-d'
option when an application invokes.

Here is an example.
$ sudo ./testpmd -c f -n 4 -d librte_pmd_null.so \
	--vdev 'eth_null0' --vdev 'eth_null1' -- -i --no-flush-rx

If testpmd is compiled with CONFIG_RTE_BUILD_SHARED_LIB, it may need to
specify more libraries using '-d' option.

v10:
- Fix driver initilization code not to return error when param is NULL.
v8:
 - Fix Makefile and add version map file.
   (Thanks to Qiu, Michael and Iremonger, Bernard)
v7:
 - Add parameter checkings.
   (Thanks to Iremonger, Bernard)
 - Remove needless "__rte_unused".
v4:
 - Fix memory leak.
   (Thanks to Iremonger, Bernard)

Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
---
 config/common_bsdapp                         |   5 +
 config/common_linuxapp                       |   5 +
 lib/Makefile                                 |   1 +
 lib/librte_pmd_null/Makefile                 |  62 +++
 lib/librte_pmd_null/rte_eth_null.c           | 543 +++++++++++++++++++++++++++
 lib/librte_pmd_null/rte_pmd_null_version.map |   4 +
 6 files changed, 620 insertions(+)
 create mode 100644 lib/librte_pmd_null/Makefile
 create mode 100644 lib/librte_pmd_null/rte_eth_null.c
 create mode 100644 lib/librte_pmd_null/rte_pmd_null_version.map

diff --git a/config/common_bsdapp b/config/common_bsdapp
index e9d07e4..d019edb 100644
--- a/config/common_bsdapp
+++ b/config/common_bsdapp
@@ -241,6 +241,11 @@ CONFIG_RTE_LIBRTE_PMD_PCAP=y
 CONFIG_RTE_LIBRTE_PMD_BOND=y
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/config/common_linuxapp b/config/common_linuxapp
index 5f7fe28..ed749f2 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -248,6 +248,11 @@ CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
 CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/lib/Makefile b/lib/Makefile
index 6575a4e..5fcbb3c 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -54,6 +54,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += librte_pmd_virtio
 DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt
 DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += librte_vhost
+DIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += librte_pmd_null
 DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash
 DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm
 DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl
diff --git a/lib/librte_pmd_null/Makefile b/lib/librte_pmd_null/Makefile
new file mode 100644
index 0000000..6472015
--- /dev/null
+++ b/lib/librte_pmd_null/Makefile
@@ -0,0 +1,62 @@
+#   BSD LICENSE
+#
+#   Copyright (C) IGEL Co.,Ltd.
+#   All rights reserved.
+#
+#   Redistribution and use in source and binary forms, with or without
+#   modification, are permitted provided that the following conditions
+#   are met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in
+#       the documentation and/or other materials provided with the
+#       distribution.
+#     * Neither the name of IGEL Co.,Ltd. nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_pmd_null.a
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+EXPORT_MAP := rte_pmd_null_version.map
+
+LIBABIVER := 1
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += rte_eth_null.c
+
+#
+# Export include files
+#
+SYMLINK-y-include +=
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_malloc
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_kvargs
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
new file mode 100644
index 0000000..7c6e583
--- /dev/null
+++ b/lib/librte_pmd_null/rte_eth_null.c
@@ -0,0 +1,543 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright (C) IGEL Co.,Ltd.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of IGEL Co.,Ltd. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_dev.h>
+#include <rte_kvargs.h>
+
+#define ETH_NULL_PACKET_SIZE_ARG	"size"
+#define ETH_NULL_PACKET_COPY_ARG	"copy"
+
+static unsigned default_packet_size = 64;
+static unsigned default_packet_copy;
+
+static const char const *valid_arguments[] = {
+	ETH_NULL_PACKET_SIZE_ARG,
+	ETH_NULL_PACKET_COPY_ARG,
+	NULL
+};
+
+struct pmd_internals;
+
+struct null_queue {
+	struct pmd_internals *internals;
+
+	struct rte_mempool *mb_pool;
+	struct rte_mbuf *dummy_packet;
+
+	rte_atomic64_t rx_pkts;
+	rte_atomic64_t tx_pkts;
+	rte_atomic64_t err_pkts;
+};
+
+struct pmd_internals {
+	unsigned packet_size;
+	unsigned packet_copy;
+	unsigned numa_node;
+
+	unsigned nb_rx_queues;
+	unsigned nb_tx_queues;
+
+	struct null_queue rx_null_queues[1];
+	struct null_queue tx_null_queues[1];
+};
+
+
+static struct ether_addr eth_addr = { .addr_bytes = {0} };
+static const char *drivername = "Null PMD";
+static struct rte_eth_link pmd_link = {
+	.link_speed = 10000,
+	.link_duplex = ETH_LINK_FULL_DUPLEX,
+	.link_status = 0
+};
+
+static uint16_t
+eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size;
+
+	if ((q ==NULL) || (bufs == NULL))
+		return 0;
+
+	packet_size = h->internals->packet_size;
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size;
+
+	if ((q ==NULL) || (bufs == NULL))
+		return 0;
+
+	packet_size = h->internals->packet_size;
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,
+					packet_size);
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+
+	if ((q ==NULL) || (bufs == NULL))
+		return 0;
+
+	for (i = 0; i < nb_bufs; i++)
+		rte_pktmbuf_free(bufs[i]);
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	if ((q ==NULL) || (bufs == NULL))
+		return 0;
+
+	for (i = 0; i < nb_bufs; i++) {
+		rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *),
+					packet_size);
+		rte_pktmbuf_free(bufs[i]);
+	}
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static int
+eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; }
+
+static int
+eth_dev_start(struct rte_eth_dev *dev)
+{
+	if (dev == NULL)
+		return -EINVAL;
+
+	dev->data->dev_link.link_status = 1;
+	return 0;
+}
+
+static void
+eth_dev_stop(struct rte_eth_dev *dev)
+{
+	if (dev == NULL)
+		return;
+
+	dev->data->dev_link.link_status = 0;
+}
+
+static int
+eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+		uint16_t nb_rx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_rxconf *rx_conf __rte_unused,
+		struct rte_mempool *mb_pool)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals;
+	unsigned packet_size;
+
+	if ((dev == NULL) || (mb_pool == NULL))
+		return -EINVAL;
+
+	if (rx_queue_id != 0)
+		return -ENODEV;
+
+	internals = dev->data->dev_private;
+	packet_size = internals->packet_size;
+
+	internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool;
+	dev->data->rx_queues[rx_queue_id] =
+		&internals->rx_null_queues[rx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->rx_null_queues[rx_queue_id].internals = internals;
+	internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+static int
+eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+		uint16_t nb_tx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals;
+	unsigned packet_size;
+
+	if (dev == NULL)
+		return -EINVAL;
+
+	if (tx_queue_id != 0)
+		return -ENODEV;
+
+	internals = dev->data->dev_private;
+	packet_size = internals->packet_size;
+
+	dev->data->tx_queues[tx_queue_id] =
+		&internals->tx_null_queues[tx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->tx_null_queues[tx_queue_id].internals = internals;
+	internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+
+static void
+eth_dev_info(struct rte_eth_dev *dev,
+		struct rte_eth_dev_info *dev_info)
+{
+	struct pmd_internals *internals;
+
+	if ((dev == NULL) || (dev_info == NULL))
+		return;
+
+	internals = dev->data->dev_private;
+	dev_info->driver_name = drivername;
+	dev_info->max_mac_addrs = 1;
+	dev_info->max_rx_pktlen = (uint32_t)-1;
+	dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;
+	dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;
+	dev_info->min_rx_bufsize = 0;
+	dev_info->pci_dev = NULL;
+}
+
+static void
+eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)
+{
+	unsigned i;
+	unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
+	const struct pmd_internals *internal;
+
+	if ((dev == NULL) || (igb_stats == NULL))
+		return;
+
+	internal = dev->data->dev_private;
+	memset(igb_stats, 0, sizeof(*igb_stats));
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_rx_queues; i++) {
+		igb_stats->q_ipackets[i] =
+			internal->rx_null_queues[i].rx_pkts.cnt;
+		rx_total += igb_stats->q_ipackets[i];
+	}
+
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_tx_queues; i++) {
+		igb_stats->q_opackets[i] =
+			internal->tx_null_queues[i].tx_pkts.cnt;
+		igb_stats->q_errors[i] =
+			internal->tx_null_queues[i].err_pkts.cnt;
+		tx_total += igb_stats->q_opackets[i];
+		tx_err_total += igb_stats->q_errors[i];
+	}
+
+	igb_stats->ipackets = rx_total;
+	igb_stats->opackets = tx_total;
+	igb_stats->oerrors = tx_err_total;
+}
+
+static void
+eth_stats_reset(struct rte_eth_dev *dev)
+{
+	unsigned i;
+	struct pmd_internals *internal;
+
+	if (dev == NULL)
+		return;
+
+	internal = dev->data->dev_private;
+	for (i = 0; i < internal->nb_rx_queues; i++)
+		internal->rx_null_queues[i].rx_pkts.cnt = 0;
+	for (i = 0; i < internal->nb_tx_queues; i++) {
+		internal->tx_null_queues[i].tx_pkts.cnt = 0;
+		internal->tx_null_queues[i].err_pkts.cnt = 0;
+	}
+}
+
+static void
+eth_queue_release(void *q)
+{
+	struct null_queue *nq;
+
+	if (q == NULL)
+		return;
+
+	nq = q;
+	if (nq->dummy_packet)
+		rte_free(nq->dummy_packet);
+}
+
+static int
+eth_link_update(struct rte_eth_dev *dev __rte_unused,
+		int wait_to_complete __rte_unused) { return 0; }
+
+static struct eth_dev_ops ops = {
+		.dev_start = eth_dev_start,
+		.dev_stop = eth_dev_stop,
+		.dev_configure = eth_dev_configure,
+		.dev_infos_get = eth_dev_info,
+		.rx_queue_setup = eth_rx_queue_setup,
+		.tx_queue_setup = eth_tx_queue_setup,
+		.rx_queue_release = eth_queue_release,
+		.tx_queue_release = eth_queue_release,
+		.link_update = eth_link_update,
+		.stats_get = eth_stats_get,
+		.stats_reset = eth_stats_reset,
+};
+
+static int
+eth_dev_null_create(const char *name,
+		const unsigned numa_node,
+		unsigned packet_size,
+		unsigned packet_copy)
+{
+	const unsigned nb_rx_queues = 1;
+	const unsigned nb_tx_queues = 1;
+	struct rte_eth_dev_data *data = NULL;
+	struct rte_pci_device *pci_dev = NULL;
+	struct pmd_internals *internals = NULL;
+	struct rte_eth_dev *eth_dev = NULL;
+
+	if (name == NULL)
+		return -EINVAL;
+
+	RTE_LOG(INFO, PMD, "Creating null ethdev on numa socket %u\n",
+			numa_node);
+
+	/* now do all data allocation - for eth_dev structure, dummy pci driver
+	 * and internal (private) data
+	 */
+	data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);
+	if (data == NULL)
+		goto error;
+
+	pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);
+	if (pci_dev == NULL)
+		goto error;
+
+	internals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node);
+	if (internals == NULL)
+		goto error;
+
+	/* reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL);
+	if (eth_dev == NULL)
+		goto error;
+
+	/* now put it all together
+	 * - store queue data in internals,
+	 * - store numa_node info in pci_driver
+	 * - point eth_dev_data to internals and pci_driver
+	 * - and point eth_dev structure to new eth_dev_data structure
+	 */
+	/* NOTE: we'll replace the data element, of originally allocated eth_dev
+	 * so the nulls are local per-process */
+
+	internals->nb_rx_queues = nb_rx_queues;
+	internals->nb_tx_queues = nb_tx_queues;
+	internals->packet_size = packet_size;
+	internals->packet_copy = packet_copy;
+	internals->numa_node = numa_node;
+
+	pci_dev->numa_node = numa_node;
+
+	data->dev_private = internals;
+	data->port_id = eth_dev->data->port_id;
+	data->nb_rx_queues = (uint16_t)nb_rx_queues;
+	data->nb_tx_queues = (uint16_t)nb_tx_queues;
+	data->dev_link = pmd_link;
+	data->mac_addrs = &eth_addr;
+
+	eth_dev->data = data;
+	eth_dev->dev_ops = &ops;
+	eth_dev->pci_dev = pci_dev;
+
+	/* finally assign rx and tx ops */
+	if (packet_copy) {
+		eth_dev->rx_pkt_burst = eth_null_copy_rx;
+		eth_dev->tx_pkt_burst = eth_null_copy_tx;
+	} else {
+		eth_dev->rx_pkt_burst = eth_null_rx;
+		eth_dev->tx_pkt_burst = eth_null_tx;
+	}
+
+	return 0;
+
+error:
+	if (data)
+		rte_free(data);
+	if (pci_dev)
+		rte_free(pci_dev);
+	if (internals)
+		rte_free(internals);
+	return -1;
+}
+
+static inline int
+get_packet_size_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_size = extra_args;
+
+	if ((value == NULL) || (extra_args == NULL))
+		return -EINVAL;
+
+	*packet_size = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_size == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static inline int
+get_packet_copy_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_copy = extra_args;
+
+	if ((value == NULL) || (extra_args == NULL))
+		return -EINVAL;
+
+	*packet_copy = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_copy == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static int
+rte_pmd_null_devinit(const char *name, const char *params)
+{
+	unsigned numa_node;
+	unsigned packet_size = default_packet_size;
+	unsigned packet_copy = default_packet_copy;
+	struct rte_kvargs *kvlist;
+	int ret;
+
+	if (name == NULL)
+		return -EINVAL;
+
+	RTE_LOG(INFO, PMD, "Initializing pmd_null for %s\n", name);
+
+	numa_node = rte_socket_id();
+
+	if (params != NULL) {
+		kvlist = rte_kvargs_parse(params, valid_arguments);
+		if (kvlist == NULL)
+			return -1;
+
+		if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) {
+
+			ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_SIZE_ARG,
+					&get_packet_size_arg, &packet_size);
+			if (ret < 0)
+				return -1;
+		}
+
+		if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) {
+
+			ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_COPY_ARG,
+					&get_packet_copy_arg, &packet_copy);
+			if (ret < 0)
+				return -1;
+		}
+	}
+
+	RTE_LOG(INFO, PMD, "Configure pmd_null: packet size is %d, "
+			"packet copy is %s\n", packet_size,
+			packet_copy ? "enabled" : "disabled");
+
+	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
+}
+
+static struct rte_driver pmd_null_drv = {
+	.name = "eth_null",
+	.type = PMD_VDEV,
+	.init = rte_pmd_null_devinit,
+};
+
+PMD_REGISTER_DRIVER(pmd_null_drv);
diff --git a/lib/librte_pmd_null/rte_pmd_null_version.map b/lib/librte_pmd_null/rte_pmd_null_version.map
new file mode 100644
index 0000000..ef35398
--- /dev/null
+++ b/lib/librte_pmd_null/rte_pmd_null_version.map
@@ -0,0 +1,4 @@
+DPDK_2.0 {
+
+	local: *;
+};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v10 2/2] librte_pmd_null: Support port hotplug function
       [not found]                                     ` <1424414516-18609-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2015-02-20  6:41                                       ` Tetsuya Mukawa
  2015-02-23  5:12                                       ` [PATCH v11 1/2] librte_pmd_null: Add Null PMD Tetsuya Mukawa
  1 sibling, 0 replies; 60+ messages in thread
From: Tetsuya Mukawa @ 2015-02-20  6:41 UTC (permalink / raw)
  To: dev-VfR2kkLFssw

This patch adds port hotplug support to Null PMD.

v9:
 - Use rte_eth_dev_release_port() instead of rte_eth_dev_free().
v7:
 - Add parameter checkings.
   (Thanks to Iremonger, Bernard)
v6:
 - Fix a parameter of rte_eth_dev_free().
v4:
 - Fix commit title.

Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
---
 lib/librte_pmd_null/rte_eth_null.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
index 7c6e583..94961bd 100644
--- a/lib/librte_pmd_null/rte_eth_null.c
+++ b/lib/librte_pmd_null/rte_eth_null.c
@@ -336,6 +336,13 @@ eth_stats_reset(struct rte_eth_dev *dev)
 	}
 }
 
+static struct eth_driver rte_null_pmd = {
+	.pci_drv = {
+		.name = "rte_null_pmd",
+		.drv_flags = RTE_PCI_DRV_DETACHABLE,
+	},
+};
+
 static void
 eth_queue_release(void *q)
 {
@@ -429,10 +436,12 @@ eth_dev_null_create(const char *name,
 	data->nb_tx_queues = (uint16_t)nb_tx_queues;
 	data->dev_link = pmd_link;
 	data->mac_addrs = &eth_addr;
+	strncpy(data->name, eth_dev->data->name, strlen(eth_dev->data->name));
 
 	eth_dev->data = data;
 	eth_dev->dev_ops = &ops;
 	eth_dev->pci_dev = pci_dev;
+	eth_dev->driver = &rte_null_pmd;
 
 	/* finally assign rx and tx ops */
 	if (packet_copy) {
@@ -534,10 +543,36 @@ rte_pmd_null_devinit(const char *name, const char *params)
 	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
 }
 
+static int
+rte_pmd_null_devuninit(const char *name)
+{
+	struct rte_eth_dev *eth_dev = NULL;
+
+	if (name == NULL)
+		return -EINVAL;
+
+	RTE_LOG(INFO, PMD, "Closing null ethdev on numa socket %u\n",
+			rte_socket_id());
+
+	/* reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocated(name);
+	if (eth_dev == NULL)
+		return -1;
+
+	rte_free(eth_dev->data->dev_private);
+	rte_free(eth_dev->data);
+	rte_free(eth_dev->pci_dev);
+
+	rte_eth_dev_release_port(eth_dev);
+
+	return 0;
+}
+
 static struct rte_driver pmd_null_drv = {
 	.name = "eth_null",
 	.type = PMD_VDEV,
 	.init = rte_pmd_null_devinit,
+	.uninit = rte_pmd_null_devuninit,
 };
 
 PMD_REGISTER_DRIVER(pmd_null_drv);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v11 1/2] librte_pmd_null: Add Null PMD
       [not found]                                     ` <1424414516-18609-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  2015-02-20  6:41                                       ` [PATCH v10 2/2] librte_pmd_null: Support port hotplug function Tetsuya Mukawa
@ 2015-02-23  5:12                                       ` Tetsuya Mukawa
       [not found]                                         ` <1424668355-8794-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  1 sibling, 1 reply; 60+ messages in thread
From: Tetsuya Mukawa @ 2015-02-23  5:12 UTC (permalink / raw)
  To: dev-VfR2kkLFssw

Null PMD is a driver of the virtual device particularly designed to measure
performance of DPDK PMDs. When an application call rx, Null PMD just allocates
mbufs and returns those. Also tx, the PMD just frees mbufs.

The PMD has following options.
- size: specify packe size allocated by RX. Default packet size is 64.
- copy: specify 1 or 0 to enable or disable copy while RX and TX.
	Default value is 0(disabled).
	This option is used for emulating more realistic data transfer.
	Copy size is equal to packet size.

To use the PMD, enable CONFIG_RTE_BUILD_SHARED_LIB in config file. Then
compile the PMD as shared library. The library can be linked using '-d'
option when an application invokes.

Here is an example.
$ sudo ./testpmd -c f -n 4 -d librte_pmd_null.so \
	--vdev 'eth_null0' --vdev 'eth_null1' -- -i --no-flush-rx

If testpmd is compiled with CONFIG_RTE_BUILD_SHARED_LIB, it may need to
specify more libraries using '-d' option.

v11:
- Fix warning of checkpatch.pl.
v10:
- Fix driver initilization code not to return error when param is NULL.
v8:
 - Fix Makefile and add version map file.
   (Thanks to Qiu, Michael and Iremonger, Bernard)
v7:
 - Add parameter checkings.
   (Thanks to Iremonger, Bernard)
 - Remove needless "__rte_unused".
v4:
 - Fix memory leak.
   (Thanks to Iremonger, Bernard)

Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
---
 config/common_bsdapp                         |   5 +
 config/common_linuxapp                       |   5 +
 lib/Makefile                                 |   1 +
 lib/librte_pmd_null/Makefile                 |  62 +++
 lib/librte_pmd_null/rte_eth_null.c           | 545 +++++++++++++++++++++++++++
 lib/librte_pmd_null/rte_pmd_null_version.map |   4 +
 6 files changed, 622 insertions(+)
 create mode 100644 lib/librte_pmd_null/Makefile
 create mode 100644 lib/librte_pmd_null/rte_eth_null.c
 create mode 100644 lib/librte_pmd_null/rte_pmd_null_version.map

diff --git a/config/common_bsdapp b/config/common_bsdapp
index c24f687..50189d6 100644
--- a/config/common_bsdapp
+++ b/config/common_bsdapp
@@ -243,6 +243,11 @@ CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB=n
 CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB_L1=n
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/config/common_linuxapp b/config/common_linuxapp
index d66b008..9ddd056 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -250,6 +250,11 @@ CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
 CONFIG_RTE_LIBRTE_PMD_XENVIRT=n
 
 #
+# Compile null PMD
+#
+CONFIG_RTE_LIBRTE_PMD_NULL=y
+
+#
 # Do prefetch of packet data within PMD driver receive function
 #
 CONFIG_RTE_PMD_PACKET_PREFETCH=y
diff --git a/lib/Makefile b/lib/Makefile
index 6575a4e..5fcbb3c 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -54,6 +54,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += librte_pmd_virtio
 DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt
 DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += librte_vhost
+DIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += librte_pmd_null
 DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash
 DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm
 DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl
diff --git a/lib/librte_pmd_null/Makefile b/lib/librte_pmd_null/Makefile
new file mode 100644
index 0000000..6472015
--- /dev/null
+++ b/lib/librte_pmd_null/Makefile
@@ -0,0 +1,62 @@
+#   BSD LICENSE
+#
+#   Copyright (C) IGEL Co.,Ltd.
+#   All rights reserved.
+#
+#   Redistribution and use in source and binary forms, with or without
+#   modification, are permitted provided that the following conditions
+#   are met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in
+#       the documentation and/or other materials provided with the
+#       distribution.
+#     * Neither the name of IGEL Co.,Ltd. nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_pmd_null.a
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+EXPORT_MAP := rte_pmd_null_version.map
+
+LIBABIVER := 1
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += rte_eth_null.c
+
+#
+# Export include files
+#
+SYMLINK-y-include +=
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_malloc
+DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_kvargs
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
new file mode 100644
index 0000000..aaa0839
--- /dev/null
+++ b/lib/librte_pmd_null/rte_eth_null.c
@@ -0,0 +1,545 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright (C) IGEL Co.,Ltd.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of IGEL Co.,Ltd. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_dev.h>
+#include <rte_kvargs.h>
+
+#define ETH_NULL_PACKET_SIZE_ARG	"size"
+#define ETH_NULL_PACKET_COPY_ARG	"copy"
+
+static unsigned default_packet_size = 64;
+static unsigned default_packet_copy;
+
+static const char const *valid_arguments[] = {
+	ETH_NULL_PACKET_SIZE_ARG,
+	ETH_NULL_PACKET_COPY_ARG,
+	NULL
+};
+
+struct pmd_internals;
+
+struct null_queue {
+	struct pmd_internals *internals;
+
+	struct rte_mempool *mb_pool;
+	struct rte_mbuf *dummy_packet;
+
+	rte_atomic64_t rx_pkts;
+	rte_atomic64_t tx_pkts;
+	rte_atomic64_t err_pkts;
+};
+
+struct pmd_internals {
+	unsigned packet_size;
+	unsigned packet_copy;
+	unsigned numa_node;
+
+	unsigned nb_rx_queues;
+	unsigned nb_tx_queues;
+
+	struct null_queue rx_null_queues[1];
+	struct null_queue tx_null_queues[1];
+};
+
+
+static struct ether_addr eth_addr = { .addr_bytes = {0} };
+static const char *drivername = "Null PMD";
+static struct rte_eth_link pmd_link = {
+	.link_speed = 10000,
+	.link_duplex = ETH_LINK_FULL_DUPLEX,
+	.link_status = 0
+};
+
+static uint16_t
+eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size;
+
+	if ((q == NULL) || (bufs == NULL))
+		return 0;
+
+	packet_size = h->internals->packet_size;
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size;
+
+	if ((q == NULL) || (bufs == NULL))
+		return 0;
+
+	packet_size = h->internals->packet_size;
+	for (i = 0; i < nb_bufs; i++) {
+		bufs[i] = rte_pktmbuf_alloc(h->mb_pool);
+		if (!bufs[i])
+			break;
+		rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,
+					packet_size);
+		bufs[i]->data_len = (uint16_t)packet_size;
+		bufs[i]->pkt_len = packet_size;
+		bufs[i]->nb_segs = 1;
+		bufs[i]->next = NULL;
+	}
+
+	rte_atomic64_add(&(h->rx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+
+	if ((q == NULL) || (bufs == NULL))
+		return 0;
+
+	for (i = 0; i < nb_bufs; i++)
+		rte_pktmbuf_free(bufs[i]);
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static uint16_t
+eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
+{
+	int i;
+	struct null_queue *h = q;
+	unsigned packet_size = h->internals->packet_size;
+
+	if ((q == NULL) || (bufs == NULL))
+		return 0;
+
+	for (i = 0; i < nb_bufs; i++) {
+		rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *),
+					packet_size);
+		rte_pktmbuf_free(bufs[i]);
+	}
+
+	rte_atomic64_add(&(h->tx_pkts), i);
+
+	return i;
+}
+
+static int
+eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; }
+
+static int
+eth_dev_start(struct rte_eth_dev *dev)
+{
+	if (dev == NULL)
+		return -EINVAL;
+
+	dev->data->dev_link.link_status = 1;
+	return 0;
+}
+
+static void
+eth_dev_stop(struct rte_eth_dev *dev)
+{
+	if (dev == NULL)
+		return;
+
+	dev->data->dev_link.link_status = 0;
+}
+
+static int
+eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+		uint16_t nb_rx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_rxconf *rx_conf __rte_unused,
+		struct rte_mempool *mb_pool)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals;
+	unsigned packet_size;
+
+	if ((dev == NULL) || (mb_pool == NULL))
+		return -EINVAL;
+
+	if (rx_queue_id != 0)
+		return -ENODEV;
+
+	internals = dev->data->dev_private;
+	packet_size = internals->packet_size;
+
+	internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool;
+	dev->data->rx_queues[rx_queue_id] =
+		&internals->rx_null_queues[rx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->rx_null_queues[rx_queue_id].internals = internals;
+	internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+static int
+eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+		uint16_t nb_tx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+	struct rte_mbuf *dummy_packet;
+	struct pmd_internals *internals;
+	unsigned packet_size;
+
+	if (dev == NULL)
+		return -EINVAL;
+
+	if (tx_queue_id != 0)
+		return -ENODEV;
+
+	internals = dev->data->dev_private;
+	packet_size = internals->packet_size;
+
+	dev->data->tx_queues[tx_queue_id] =
+		&internals->tx_null_queues[tx_queue_id];
+	dummy_packet = rte_zmalloc_socket(NULL,
+			packet_size, 0, internals->numa_node);
+	if (dummy_packet == NULL)
+		return -ENOMEM;
+
+	internals->tx_null_queues[tx_queue_id].internals = internals;
+	internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet;
+
+	return 0;
+}
+
+
+static void
+eth_dev_info(struct rte_eth_dev *dev,
+		struct rte_eth_dev_info *dev_info)
+{
+	struct pmd_internals *internals;
+
+	if ((dev == NULL) || (dev_info == NULL))
+		return;
+
+	internals = dev->data->dev_private;
+	dev_info->driver_name = drivername;
+	dev_info->max_mac_addrs = 1;
+	dev_info->max_rx_pktlen = (uint32_t)-1;
+	dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;
+	dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;
+	dev_info->min_rx_bufsize = 0;
+	dev_info->pci_dev = NULL;
+}
+
+static void
+eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)
+{
+	unsigned i;
+	unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
+	const struct pmd_internals *internal;
+
+	if ((dev == NULL) || (igb_stats == NULL))
+		return;
+
+	internal = dev->data->dev_private;
+	memset(igb_stats, 0, sizeof(*igb_stats));
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_rx_queues; i++) {
+		igb_stats->q_ipackets[i] =
+			internal->rx_null_queues[i].rx_pkts.cnt;
+		rx_total += igb_stats->q_ipackets[i];
+	}
+
+	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
+			i < internal->nb_tx_queues; i++) {
+		igb_stats->q_opackets[i] =
+			internal->tx_null_queues[i].tx_pkts.cnt;
+		igb_stats->q_errors[i] =
+			internal->tx_null_queues[i].err_pkts.cnt;
+		tx_total += igb_stats->q_opackets[i];
+		tx_err_total += igb_stats->q_errors[i];
+	}
+
+	igb_stats->ipackets = rx_total;
+	igb_stats->opackets = tx_total;
+	igb_stats->oerrors = tx_err_total;
+}
+
+static void
+eth_stats_reset(struct rte_eth_dev *dev)
+{
+	unsigned i;
+	struct pmd_internals *internal;
+
+	if (dev == NULL)
+		return;
+
+	internal = dev->data->dev_private;
+	for (i = 0; i < internal->nb_rx_queues; i++)
+		internal->rx_null_queues[i].rx_pkts.cnt = 0;
+	for (i = 0; i < internal->nb_tx_queues; i++) {
+		internal->tx_null_queues[i].tx_pkts.cnt = 0;
+		internal->tx_null_queues[i].err_pkts.cnt = 0;
+	}
+}
+
+static void
+eth_queue_release(void *q)
+{
+	struct null_queue *nq;
+
+	if (q == NULL)
+		return;
+
+	nq = q;
+	if (nq->dummy_packet)
+		rte_free(nq->dummy_packet);
+}
+
+static int
+eth_link_update(struct rte_eth_dev *dev __rte_unused,
+		int wait_to_complete __rte_unused) { return 0; }
+
+static struct eth_dev_ops ops = {
+		.dev_start = eth_dev_start,
+		.dev_stop = eth_dev_stop,
+		.dev_configure = eth_dev_configure,
+		.dev_infos_get = eth_dev_info,
+		.rx_queue_setup = eth_rx_queue_setup,
+		.tx_queue_setup = eth_tx_queue_setup,
+		.rx_queue_release = eth_queue_release,
+		.tx_queue_release = eth_queue_release,
+		.link_update = eth_link_update,
+		.stats_get = eth_stats_get,
+		.stats_reset = eth_stats_reset,
+};
+
+static int
+eth_dev_null_create(const char *name,
+		const unsigned numa_node,
+		unsigned packet_size,
+		unsigned packet_copy)
+{
+	const unsigned nb_rx_queues = 1;
+	const unsigned nb_tx_queues = 1;
+	struct rte_eth_dev_data *data = NULL;
+	struct rte_pci_device *pci_dev = NULL;
+	struct pmd_internals *internals = NULL;
+	struct rte_eth_dev *eth_dev = NULL;
+
+	if (name == NULL)
+		return -EINVAL;
+
+	RTE_LOG(INFO, PMD, "Creating null ethdev on numa socket %u\n",
+			numa_node);
+
+	/* now do all data allocation - for eth_dev structure, dummy pci driver
+	 * and internal (private) data
+	 */
+	data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);
+	if (data == NULL)
+		goto error;
+
+	pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);
+	if (pci_dev == NULL)
+		goto error;
+
+	internals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node);
+	if (internals == NULL)
+		goto error;
+
+	/* reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL);
+	if (eth_dev == NULL)
+		goto error;
+
+	/* now put it all together
+	 * - store queue data in internals,
+	 * - store numa_node info in pci_driver
+	 * - point eth_dev_data to internals and pci_driver
+	 * - and point eth_dev structure to new eth_dev_data structure
+	 */
+	/* NOTE: we'll replace the data element, of originally allocated eth_dev
+	 * so the nulls are local per-process */
+
+	internals->nb_rx_queues = nb_rx_queues;
+	internals->nb_tx_queues = nb_tx_queues;
+	internals->packet_size = packet_size;
+	internals->packet_copy = packet_copy;
+	internals->numa_node = numa_node;
+
+	pci_dev->numa_node = numa_node;
+
+	data->dev_private = internals;
+	data->port_id = eth_dev->data->port_id;
+	data->nb_rx_queues = (uint16_t)nb_rx_queues;
+	data->nb_tx_queues = (uint16_t)nb_tx_queues;
+	data->dev_link = pmd_link;
+	data->mac_addrs = &eth_addr;
+
+	eth_dev->data = data;
+	eth_dev->dev_ops = &ops;
+	eth_dev->pci_dev = pci_dev;
+
+	/* finally assign rx and tx ops */
+	if (packet_copy) {
+		eth_dev->rx_pkt_burst = eth_null_copy_rx;
+		eth_dev->tx_pkt_burst = eth_null_copy_tx;
+	} else {
+		eth_dev->rx_pkt_burst = eth_null_rx;
+		eth_dev->tx_pkt_burst = eth_null_tx;
+	}
+
+	return 0;
+
+error:
+	if (data)
+		rte_free(data);
+	if (pci_dev)
+		rte_free(pci_dev);
+	if (internals)
+		rte_free(internals);
+	return -1;
+}
+
+static inline int
+get_packet_size_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_size = extra_args;
+
+	if ((value == NULL) || (extra_args == NULL))
+		return -EINVAL;
+
+	*packet_size = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_size == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static inline int
+get_packet_copy_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	const char *a = value;
+	unsigned *packet_copy = extra_args;
+
+	if ((value == NULL) || (extra_args == NULL))
+		return -EINVAL;
+
+	*packet_copy = (unsigned)strtoul(a, NULL, 0);
+	if (*packet_copy == UINT_MAX)
+		return -1;
+
+	return 0;
+}
+
+static int
+rte_pmd_null_devinit(const char *name, const char *params)
+{
+	unsigned numa_node;
+	unsigned packet_size = default_packet_size;
+	unsigned packet_copy = default_packet_copy;
+	struct rte_kvargs *kvlist;
+	int ret;
+
+	if (name == NULL)
+		return -EINVAL;
+
+	RTE_LOG(INFO, PMD, "Initializing pmd_null for %s\n", name);
+
+	numa_node = rte_socket_id();
+
+	if (params != NULL) {
+		kvlist = rte_kvargs_parse(params, valid_arguments);
+		if (kvlist == NULL)
+			return -1;
+
+		if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) {
+
+			ret = rte_kvargs_process(kvlist,
+					ETH_NULL_PACKET_SIZE_ARG,
+					&get_packet_size_arg, &packet_size);
+			if (ret < 0)
+				return -1;
+		}
+
+		if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) {
+
+			ret = rte_kvargs_process(kvlist,
+					ETH_NULL_PACKET_COPY_ARG,
+					&get_packet_copy_arg, &packet_copy);
+			if (ret < 0)
+				return -1;
+		}
+	}
+
+	RTE_LOG(INFO, PMD, "Configure pmd_null: packet size is %d, "
+			"packet copy is %s\n", packet_size,
+			packet_copy ? "enabled" : "disabled");
+
+	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
+}
+
+static struct rte_driver pmd_null_drv = {
+	.name = "eth_null",
+	.type = PMD_VDEV,
+	.init = rte_pmd_null_devinit,
+};
+
+PMD_REGISTER_DRIVER(pmd_null_drv);
diff --git a/lib/librte_pmd_null/rte_pmd_null_version.map b/lib/librte_pmd_null/rte_pmd_null_version.map
new file mode 100644
index 0000000..ef35398
--- /dev/null
+++ b/lib/librte_pmd_null/rte_pmd_null_version.map
@@ -0,0 +1,4 @@
+DPDK_2.0 {
+
+	local: *;
+};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v11 2/2] librte_pmd_null: Support port hotplug function
       [not found]                                         ` <1424668355-8794-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2015-02-23  5:12                                           ` Tetsuya Mukawa
       [not found]                                             ` <1424668355-8794-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
  0 siblings, 1 reply; 60+ messages in thread
From: Tetsuya Mukawa @ 2015-02-23  5:12 UTC (permalink / raw)
  To: dev-VfR2kkLFssw

This patch adds port hotplug support to Null PMD.

v9:
 - Use rte_eth_dev_release_port() instead of rte_eth_dev_free().
v7:
 - Add parameter checkings.
   (Thanks to Iremonger, Bernard)
v6:
 - Fix a parameter of rte_eth_dev_free().
v4:
 - Fix commit title.

Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
---
 lib/librte_pmd_null/rte_eth_null.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
index aaa0839..bb10276 100644
--- a/lib/librte_pmd_null/rte_eth_null.c
+++ b/lib/librte_pmd_null/rte_eth_null.c
@@ -336,6 +336,13 @@ eth_stats_reset(struct rte_eth_dev *dev)
 	}
 }
 
+static struct eth_driver rte_null_pmd = {
+	.pci_drv = {
+		.name = "rte_null_pmd",
+		.drv_flags = RTE_PCI_DRV_DETACHABLE,
+	},
+};
+
 static void
 eth_queue_release(void *q)
 {
@@ -429,10 +436,12 @@ eth_dev_null_create(const char *name,
 	data->nb_tx_queues = (uint16_t)nb_tx_queues;
 	data->dev_link = pmd_link;
 	data->mac_addrs = &eth_addr;
+	strncpy(data->name, eth_dev->data->name, strlen(eth_dev->data->name));
 
 	eth_dev->data = data;
 	eth_dev->dev_ops = &ops;
 	eth_dev->pci_dev = pci_dev;
+	eth_dev->driver = &rte_null_pmd;
 
 	/* finally assign rx and tx ops */
 	if (packet_copy) {
@@ -536,10 +545,36 @@ rte_pmd_null_devinit(const char *name, const char *params)
 	return eth_dev_null_create(name, numa_node, packet_size, packet_copy);
 }
 
+static int
+rte_pmd_null_devuninit(const char *name)
+{
+	struct rte_eth_dev *eth_dev = NULL;
+
+	if (name == NULL)
+		return -EINVAL;
+
+	RTE_LOG(INFO, PMD, "Closing null ethdev on numa socket %u\n",
+			rte_socket_id());
+
+	/* reserve an ethdev entry */
+	eth_dev = rte_eth_dev_allocated(name);
+	if (eth_dev == NULL)
+		return -1;
+
+	rte_free(eth_dev->data->dev_private);
+	rte_free(eth_dev->data);
+	rte_free(eth_dev->pci_dev);
+
+	rte_eth_dev_release_port(eth_dev);
+
+	return 0;
+}
+
 static struct rte_driver pmd_null_drv = {
 	.name = "eth_null",
 	.type = PMD_VDEV,
 	.init = rte_pmd_null_devinit,
+	.uninit = rte_pmd_null_devuninit,
 };
 
 PMD_REGISTER_DRIVER(pmd_null_drv);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* Re: [PATCH v11 2/2] librte_pmd_null: Support port hotplug function
       [not found]                                             ` <1424668355-8794-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
@ 2015-02-25 23:35                                               ` Thomas Monjalon
  2015-02-26  0:49                                                 ` Stephen Hemminger
  0 siblings, 1 reply; 60+ messages in thread
From: Thomas Monjalon @ 2015-02-25 23:35 UTC (permalink / raw)
  To: Tetsuya Mukawa; +Cc: dev-VfR2kkLFssw

> This patch adds port hotplug support to Null PMD.
> 
> v9:
>  - Use rte_eth_dev_release_port() instead of rte_eth_dev_free().
> v7:
>  - Add parameter checkings.
>    (Thanks to Iremonger, Bernard)
> v6:
>  - Fix a parameter of rte_eth_dev_free().
> v4:
>  - Fix commit title.
> 
> Signed-off-by: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>

Applied, thanks

I assumed you are OK to be the maintainer of Null PMD.

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v11 2/2] librte_pmd_null: Support port hotplug function
  2015-02-25 23:35                                               ` Thomas Monjalon
@ 2015-02-26  0:49                                                 ` Stephen Hemminger
  2015-02-26  7:03                                                   ` Thomas Monjalon
  0 siblings, 1 reply; 60+ messages in thread
From: Stephen Hemminger @ 2015-02-26  0:49 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev-VfR2kkLFssw

Build fails if HOTPLUG is disabled

== Build lib/librte_ether
  CC rte_ethdev.o
/var/src/dpdk/lib/librte_ether/rte_ethdev.c:430:1: error: ‘rte_eth_dev_get_device_type’ defined but not used [-Werror=unused-function]
 rte_eth_dev_get_device_type(uint8_t port_id)
 ^
/var/src/dpdk/lib/librte_ether/rte_ethdev.c:438:1: error: ‘rte_eth_dev_save’ defined but not used [-Werror=unused-function]
 rte_eth_dev_save(struct rte_eth_dev *devs, size_t size)
 ^
/var/src/dpdk/lib/librte_ether/rte_ethdev.c:450:1: error: ‘rte_eth_dev_get_changed_port’ defined but not used [-Werror=unused-function]
 rte_eth_dev_get_changed_port(struct rte_eth_dev *devs, uint8_t *port_id)
 ^
/var/src/dpdk/lib/librte_ether/rte_ethdev.c:464:1: error: ‘rte_eth_dev_get_addr_by_port’ defined but not used [-Werror=unused-function]
 rte_eth_dev_get_addr_by_port(uint8_t port_id, struct rte_pci_addr *addr)
 ^
/var/src/dpdk/lib/librte_ether/rte_ethdev.c:481:1: error: ‘rte_eth_dev_get_name_by_port’ defined but not used [-Werror=unused-function]
 rte_eth_dev_get_name_by_port(uint8_t port_id, char *name)
 ^
/var/src/dpdk/lib/librte_ether/rte_ethdev.c:503:1: error: ‘rte_eth_dev_is_detachable’ defined but not used [-Werror=unused-function]
 rte_eth_dev_is_detachable(uint8_t port_id)
 ^
cc1: all warnings being treated as errors

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v11 2/2] librte_pmd_null: Support port hotplug function
  2015-02-26  0:49                                                 ` Stephen Hemminger
@ 2015-02-26  7:03                                                   ` Thomas Monjalon
  2015-02-26  9:06                                                     ` Tetsuya Mukawa
  0 siblings, 1 reply; 60+ messages in thread
From: Thomas Monjalon @ 2015-02-26  7:03 UTC (permalink / raw)
  To: Stephen Hemminger, Tetsuya Mukawa; +Cc: dev-VfR2kkLFssw

2015-02-25 16:49, Stephen Hemminger:
> Build fails if HOTPLUG is disabled

OK thanks for reporting.
Actually there is no good reason to disable hotplug on Linux.
Though it means that it's impossible to build on FreeBSD.

Tetsuya, the right fix is to remove this option.
You should manage to graceful degrades hotplug in not supported
cases supported: devices cannot be detachable in case of VFIO or nic_uio.
What about uio_pci_generic?

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v11 2/2] librte_pmd_null: Support port hotplug function
  2015-02-26  7:03                                                   ` Thomas Monjalon
@ 2015-02-26  9:06                                                     ` Tetsuya Mukawa
       [not found]                                                       ` <CAKU8wkcwLqHnHSx3qREXVcQJZQJpZ0rWtDu7We=kGM9iG4zjSA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 60+ messages in thread
From: Tetsuya Mukawa @ 2015-02-26  9:06 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev-VfR2kkLFssw

2015-02-26 16:03 GMT+09:00 Thomas Monjalon <thomas.monjalon-pdR9zngts4EAvxtiuMwx3w@public.gmane.org>:
> 2015-02-25 16:49, Stephen Hemminger:
>> Build fails if HOTPLUG is disabled

Hi Stephen,

I appreciate for you reporting.

>
> OK thanks for reporting.
> Actually there is no good reason to disable hotplug on Linux.
> Though it means that it's impossible to build on FreeBSD.
>
> Tetsuya, the right fix is to remove this option.

Hi Thomas,

Yes, I agree with it. I will add some codes to remove the option.
Please let me have a few days, I need to prepare BSD machine for compile test.

> You should manage to graceful degrades hotplug in not supported
> cases supported: devices cannot be detachable in case of VFIO or nic_uio.
> What about uio_pci_generic?

We cannot detach a vfio device so far. But we can detach a igb_uio and
uio_pci_generic device.
About a vfio ddevice, I haven't checked related code yet, but I guess
I will submit code to detach a vfio device in post-rc1.

Thanks,
Tetsuya

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v11 2/2] librte_pmd_null: Support port hotplug function
       [not found]                                                       ` <CAKU8wkcwLqHnHSx3qREXVcQJZQJpZ0rWtDu7We=kGM9iG4zjSA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2015-02-26 10:57                                                         ` Thomas Monjalon
  2015-02-26 11:50                                                           ` Tetsuya Mukawa
  2015-03-04  3:37                                                           ` Tetsuya Mukawa
  2015-02-26 12:21                                                         ` Mcnamara, John
  1 sibling, 2 replies; 60+ messages in thread
From: Thomas Monjalon @ 2015-02-26 10:57 UTC (permalink / raw)
  To: Tetsuya Mukawa; +Cc: dev-VfR2kkLFssw

2015-02-26 18:06, Tetsuya Mukawa:
> 2015-02-26 16:03 GMT+09:00 Thomas Monjalon <thomas.monjalon-pdR9zngts4EAvxtiuMwx3w@public.gmane.org>:
> > 2015-02-25 16:49, Stephen Hemminger:
> >> Build fails if HOTPLUG is disabled
> 
> Hi Stephen,
> 
> I appreciate for you reporting.
> 
> >
> > OK thanks for reporting.
> > Actually there is no good reason to disable hotplug on Linux.
> > Though it means that it's impossible to build on FreeBSD.
> >
> > Tetsuya, the right fix is to remove this option.
> 
> Hi Thomas,
> 
> Yes, I agree with it. I will add some codes to remove the option.
> Please let me have a few days, I need to prepare BSD machine for compile test.
> 
> > You should manage to graceful degrades hotplug in not supported
> > cases supported: devices cannot be detachable in case of VFIO or nic_uio.
> > What about uio_pci_generic?
> 
> We cannot detach a vfio device so far. But we can detach a igb_uio and
> uio_pci_generic device.
> About a vfio ddevice, I haven't checked related code yet, but I guess
> I will submit code to detach a vfio device in post-rc1.

OK thanks.
I made a quick fix (moving #ifdef) waiting the option removal:
	http://dpdk.org/browse/dpdk/commit/?id=7609e6609350

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v11 2/2] librte_pmd_null: Support port hotplug function
  2015-02-26 10:57                                                         ` Thomas Monjalon
@ 2015-02-26 11:50                                                           ` Tetsuya Mukawa
  2015-03-04  3:37                                                           ` Tetsuya Mukawa
  1 sibling, 0 replies; 60+ messages in thread
From: Tetsuya Mukawa @ 2015-02-26 11:50 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev-VfR2kkLFssw

2015-02-26 19:57 GMT+09:00 Thomas Monjalon <thomas.monjalon-pdR9zngts4EAvxtiuMwx3w@public.gmane.org>:
> 2015-02-26 18:06, Tetsuya Mukawa:
>> 2015-02-26 16:03 GMT+09:00 Thomas Monjalon <thomas.monjalon-pdR9zngts4EAvxtiuMwx3w@public.gmane.org>:
>> > 2015-02-25 16:49, Stephen Hemminger:
>> >> Build fails if HOTPLUG is disabled
>>
>> Hi Stephen,
>>
>> I appreciate for you reporting.
>>
>> >
>> > OK thanks for reporting.
>> > Actually there is no good reason to disable hotplug on Linux.
>> > Though it means that it's impossible to build on FreeBSD.
>> >
>> > Tetsuya, the right fix is to remove this option.
>>
>> Hi Thomas,
>>
>> Yes, I agree with it. I will add some codes to remove the option.
>> Please let me have a few days, I need to prepare BSD machine for compile test.
>>
>> > You should manage to graceful degrades hotplug in not supported
>> > cases supported: devices cannot be detachable in case of VFIO or nic_uio.
>> > What about uio_pci_generic?
>>
>> We cannot detach a vfio device so far. But we can detach a igb_uio and
>> uio_pci_generic device.
>> About a vfio ddevice, I haven't checked related code yet, but I guess
>> I will submit code to detach a vfio device in post-rc1.
>
> OK thanks.
> I made a quick fix (moving #ifdef) waiting the option removal:
>         http://dpdk.org/browse/dpdk/commit/?id=7609e6609350
>

Thank you so much for that.

Tetsuya,

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v11 2/2] librte_pmd_null: Support port hotplug function
       [not found]                                                       ` <CAKU8wkcwLqHnHSx3qREXVcQJZQJpZ0rWtDu7We=kGM9iG4zjSA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  2015-02-26 10:57                                                         ` Thomas Monjalon
@ 2015-02-26 12:21                                                         ` Mcnamara, John
       [not found]                                                           ` <B27915DBBA3421428155699D51E4CFE2EC8A08-kPTMFJFq+rELt2AQoY/u9bfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  1 sibling, 1 reply; 60+ messages in thread
From: Mcnamara, John @ 2015-02-26 12:21 UTC (permalink / raw)
  To: Tetsuya Mukawa, Thomas Monjalon; +Cc: dev-VfR2kkLFssw

Hi,

The HEAD doesn't compile with gcc 4.7.2:

    $ git clone http://dpdk.org/git/dpdk
    $ cd dpdk
    $ make T=x86_64-native-linuxapp-gcc -j install 

    ...
    == Build lib/librte_pipeline
      SYMLINK-FILE include/rte_pipeline.h
      CC rte_pipeline.o
    /tmp/dpdk/lib/librte_pmd_null/rte_eth_null.c: In function 'eth_stats_get':

    /tmp/dpdk/lib/librte_pmd_null/rte_eth_null.c:302:28:
        error: array subscript is above array bounds [-Werror=array-bounds]
    /tmp/dpdk/lib/librte_pmd_null/rte_eth_null.c:302:28: 
        error: array subscript is above array bounds [-Werror=array-bounds]
    /tmp/dpdk/lib/librte_pmd_null/rte_eth_null.c:302:28: 
        error: array subscript is above array bounds [-Werror=array-bounds]
    ...

    cc1: all warnings being treated as errors
    make[5]: *** [rte_eth_null.o] Error 1
    make[4]: *** [librte_pmd_null] Error 2


The following commit introduced this issue:

    $ git bisect good                              
    c743e50c475f73edf78e5ba26445d7c6ea217f40 is the first bad commit
    commit c743e50c475f73edf78e5ba26445d7c6ea217f40
    Author: Tetsuya Mukawa <mukawa@igel.co.jp>
    Date:   Mon Feb 23 14:12:34 2015 +0900

        null: new poll mode driver

        
I don't see the issue with gcc 4.9.

Regards,

John

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v11 2/2] librte_pmd_null: Support port hotplug function
       [not found]                                                           ` <B27915DBBA3421428155699D51E4CFE2EC8A08-kPTMFJFq+rELt2AQoY/u9bfspsVTdybXVpNB7YpNyf8@public.gmane.org>
@ 2015-02-26 15:36                                                             ` Mcnamara, John
       [not found]                                                               ` <B27915DBBA3421428155699D51E4CFE2EC8B34-kPTMFJFq+rELt2AQoY/u9bfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  2015-02-27 23:29                                                             ` Thomas Monjalon
  1 sibling, 1 reply; 60+ messages in thread
From: Mcnamara, John @ 2015-02-26 15:36 UTC (permalink / raw)
  To: Mcnamara, John, Tetsuya Mukawa, Thomas Monjalon; +Cc: dev-VfR2kkLFssw

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Mcnamara, John
> Sent: Thursday, February 26, 2015 12:21 PM
> To: Tetsuya Mukawa; Thomas Monjalon
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v11 2/2] librte_pmd_null: Support port
> hotplug function
> 
> The following commit introduced this issue:
> 
>     $ git bisect good
>     c743e50c475f73edf78e5ba26445d7c6ea217f40 is the first bad commit
>     commit c743e50c475f73edf78e5ba26445d7c6ea217f40

Hi,

The above commit also has throws a warning with ICC:

    lib/librte_pmd_null/rte_eth_null.c(47): error #83:
        type qualifier specified more than once

      static const char const *valid_arguments[] = {
                        ^

                        
An earlier commit also throws a warning with ICC:
             

    lib/librte_pmd_null/rte_eth_null.c(47): error #83: 
            type qualifier specified more than once

            static const char const *valid_arguments[] = {
            ^                        

Commit:

    92d94d3744d7760d8d5e490be810612cf4a9cfb0 is the first bad commit
    commit 92d94d3744d7760d8d5e490be810612cf4a9cfb0
    Author: Tetsuya Mukawa <mukawa@igel.co.jp>
    Date:   Thu Feb 26 04:32:26 2015 +0900

        ethdev: attach or detach port


I applied the following patch to fix these issues, (in order to test with the HEAD). You can review them to see if they are valid and apply something similar:

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index bb94ccb..6ea7a17 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -433,7 +433,7 @@ static enum rte_eth_dev_type
 rte_eth_dev_get_device_type(uint8_t port_id)
 {
        if (!rte_eth_dev_is_valid_port(port_id))
-               return -1;
+               return RTE_ETH_DEV_UNKNOWN;
        return rte_eth_devices[port_id].dev_type;
 }
 
diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
index bb10276..3ef5842 100644
--- a/lib/librte_pmd_null/rte_eth_null.c
+++ b/lib/librte_pmd_null/rte_eth_null.c
@@ -44,7 +44,7 @@
 static unsigned default_packet_size = 64;
 static unsigned default_packet_copy;
 
-static const char const *valid_arguments[] = {
+static const char *valid_arguments[] = {
        ETH_NULL_PACKET_SIZE_ARG,
        ETH_NULL_PACKET_COPY_ARG,
        NULL

       
John.
-- 

        
                        
                        
                        
                        

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* Re: [PATCH v11 2/2] librte_pmd_null: Support port hotplug function
       [not found]                                                               ` <B27915DBBA3421428155699D51E4CFE2EC8B34-kPTMFJFq+rELt2AQoY/u9bfspsVTdybXVpNB7YpNyf8@public.gmane.org>
@ 2015-02-27  1:31                                                                 ` Tetsuya Mukawa
  0 siblings, 0 replies; 60+ messages in thread
From: Tetsuya Mukawa @ 2015-02-27  1:31 UTC (permalink / raw)
  To: Mcnamara, John, Thomas Monjalon; +Cc: dev-VfR2kkLFssw

On 2015/02/27 0:36, Mcnamara, John wrote:
>> -----Original Message-----
>> From: dev [mailto:dev-bounces-VfR2kkLFssw@public.gmane.org] On Behalf Of Mcnamara, John
>> Sent: Thursday, February 26, 2015 12:21 PM
>> To: Tetsuya Mukawa; Thomas Monjalon
>> Cc: dev-VfR2kkLFssw@public.gmane.org
>> Subject: Re: [dpdk-dev] [PATCH v11 2/2] librte_pmd_null: Support port
>> hotplug function
>>
>> The following commit introduced this issue:
>>
>>     $ git bisect good
>>     c743e50c475f73edf78e5ba26445d7c6ea217f40 is the first bad commit
>>     commit c743e50c475f73edf78e5ba26445d7c6ea217f40
> Hi,
>
> The above commit also has throws a warning with ICC:
>
>     lib/librte_pmd_null/rte_eth_null.c(47): error #83:
>         type qualifier specified more than once
>
>       static const char const *valid_arguments[] = {
>                         ^
>
>                         
> An earlier commit also throws a warning with ICC:
>              
>
>     lib/librte_pmd_null/rte_eth_null.c(47): error #83: 
>             type qualifier specified more than once
>
>             static const char const *valid_arguments[] = {
>             ^                        
>
> Commit:
>
>     92d94d3744d7760d8d5e490be810612cf4a9cfb0 is the first bad commit
>     commit 92d94d3744d7760d8d5e490be810612cf4a9cfb0
>     Author: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
>     Date:   Thu Feb 26 04:32:26 2015 +0900
>
>         ethdev: attach or detach port
>
>
> I applied the following patch to fix these issues, (in order to test with the HEAD). You can review them to see if they are valid and apply something similar:
>
> diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
> index bb94ccb..6ea7a17 100644
> --- a/lib/librte_ether/rte_ethdev.c
> +++ b/lib/librte_ether/rte_ethdev.c
> @@ -433,7 +433,7 @@ static enum rte_eth_dev_type
>  rte_eth_dev_get_device_type(uint8_t port_id)
>  {
>         if (!rte_eth_dev_is_valid_port(port_id))
> -               return -1;
> +               return RTE_ETH_DEV_UNKNOWN;
>         return rte_eth_devices[port_id].dev_type;
>  }
>  
> diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c
> index bb10276..3ef5842 100644
> --- a/lib/librte_pmd_null/rte_eth_null.c
> +++ b/lib/librte_pmd_null/rte_eth_null.c
> @@ -44,7 +44,7 @@
>  static unsigned default_packet_size = 64;
>  static unsigned default_packet_copy;
>  
> -static const char const *valid_arguments[] = {
> +static const char *valid_arguments[] = {
>         ETH_NULL_PACKET_SIZE_ARG,
>         ETH_NULL_PACKET_COPY_ARG,
>         NULL
>
>        
> John.

Hi Mcnamara and Stephen,

I appreciate for reporting.
I start checking all compile issues of null pmd.

Thanks,
Tetsuya

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v11 2/2] librte_pmd_null: Support port hotplug function
       [not found]                                                           ` <B27915DBBA3421428155699D51E4CFE2EC8A08-kPTMFJFq+rELt2AQoY/u9bfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  2015-02-26 15:36                                                             ` Mcnamara, John
@ 2015-02-27 23:29                                                             ` Thomas Monjalon
  1 sibling, 0 replies; 60+ messages in thread
From: Thomas Monjalon @ 2015-02-27 23:29 UTC (permalink / raw)
  To: Mcnamara, John; +Cc: dev-VfR2kkLFssw

2015-02-26 12:21, Mcnamara, John:
> Hi,
> 
> The HEAD doesn't compile with gcc 4.7.2:
> 
>     $ git clone http://dpdk.org/git/dpdk
>     $ cd dpdk
>     $ make T=x86_64-native-linuxapp-gcc -j install 
> 
>     ...
>     == Build lib/librte_pipeline
>       SYMLINK-FILE include/rte_pipeline.h
>       CC rte_pipeline.o
>     /tmp/dpdk/lib/librte_pmd_null/rte_eth_null.c: In function 'eth_stats_get':
> 
>     /tmp/dpdk/lib/librte_pmd_null/rte_eth_null.c:302:28:
>         error: array subscript is above array bounds [-Werror=array-bounds]
>     /tmp/dpdk/lib/librte_pmd_null/rte_eth_null.c:302:28: 
>         error: array subscript is above array bounds [-Werror=array-bounds]
>     /tmp/dpdk/lib/librte_pmd_null/rte_eth_null.c:302:28: 
>         error: array subscript is above array bounds [-Werror=array-bounds]
>     ...
> 
>     cc1: all warnings being treated as errors
>     make[5]: *** [rte_eth_null.o] Error 1
>     make[4]: *** [librte_pmd_null] Error 2
> 
> 
> The following commit introduced this issue:
> 
>     $ git bisect good                              
>     c743e50c475f73edf78e5ba26445d7c6ea217f40 is the first bad commit
>     commit c743e50c475f73edf78e5ba26445d7c6ea217f40
>     Author: Tetsuya Mukawa <mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
>     Date:   Mon Feb 23 14:12:34 2015 +0900
> 
>         null: new poll mode driver
> 
>         
> I don't see the issue with gcc 4.9.

Fixed: http://dpdk.org/browse/dpdk/commit/?id=e34550c8b97826

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v11 2/2] librte_pmd_null: Support port hotplug function
  2015-02-26 10:57                                                         ` Thomas Monjalon
  2015-02-26 11:50                                                           ` Tetsuya Mukawa
@ 2015-03-04  3:37                                                           ` Tetsuya Mukawa
  1 sibling, 0 replies; 60+ messages in thread
From: Tetsuya Mukawa @ 2015-03-04  3:37 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev-VfR2kkLFssw

2015-02-26 19:57 GMT+09:00 Thomas Monjalon <thomas.monjalon-pdR9zngts4EAvxtiuMwx3w@public.gmane.org>:
> 2015-02-26 18:06, Tetsuya Mukawa:
>> 2015-02-26 16:03 GMT+09:00 Thomas Monjalon <thomas.monjalon-pdR9zngts4EAvxtiuMwx3w@public.gmane.org>:
>> > 2015-02-25 16:49, Stephen Hemminger:
>> >> Build fails if HOTPLUG is disabled
>>
>> Hi Stephen,
>>
>> I appreciate for you reporting.
>>
>> >
>> > OK thanks for reporting.
>> > Actually there is no good reason to disable hotplug on Linux.
>> > Though it means that it's impossible to build on FreeBSD.
>> >
>> > Tetsuya, the right fix is to remove this option.
>>
>> Hi Thomas,
>>
>> Yes, I agree with it. I will add some codes to remove the option.
>> Please let me have a few days, I need to prepare BSD machine for compile test.
>>
>> > You should manage to graceful degrades hotplug in not supported
>> > cases supported: devices cannot be detachable in case of VFIO or nic_uio.
>> > What about uio_pci_generic?
>>
>> We cannot detach a vfio device so far. But we can detach a igb_uio and
>> uio_pci_generic device.
>> About a vfio ddevice, I haven't checked related code yet, but I guess
>> I will submit code to detach a vfio device in post-rc1.
>
> OK thanks.
> I made a quick fix (moving #ifdef) waiting the option removal:
>         http://dpdk.org/browse/dpdk/commit/?id=7609e6609350
>

Hi Thomas,

I submit the patches to remove HOTPLUG config macro.

Thanks,
Tetsuya

^ permalink raw reply	[flat|nested] 60+ messages in thread

end of thread, other threads:[~2015-03-04  3:37 UTC | newest]

Thread overview: 60+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <mukawa@igel.co.jp>
2014-09-19 12:27 ` [RFC] PMD for performance measurement mukawa-AlSX/UN32fvPDbFq/vQRIQ
     [not found]   ` <1411129659-7132-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2014-09-19 12:27     ` [RFC] librte_pmd_null: Add null PMD mukawa-AlSX/UN32fvPDbFq/vQRIQ
     [not found]       ` <1411129659-7132-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2014-09-22  7:46         ` Ivan Boule
     [not found]           ` <541FD3BD.2060606-pdR9zngts4EAvxtiuMwx3w@public.gmane.org>
2014-09-22  8:07             ` Tetsuya Mukawa
2014-09-30  9:56 ` [PATCH 0/2] PMD for performance measurement mukawa-AlSX/UN32fvPDbFq/vQRIQ
     [not found]   ` <1412070970-5625-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2014-09-30  9:56     ` [PATCH 1/2] librte_pmd_null: Add null PMD mukawa-AlSX/UN32fvPDbFq/vQRIQ
     [not found]       ` <1412070970-5625-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2014-09-30 13:05         ` Thomas Monjalon
2014-10-01  1:41           ` Tetsuya Mukawa
2014-09-30  9:56     ` [PATCH 2/2] librte_pmd_null: Enable librte_pmd_null mukawa-AlSX/UN32fvPDbFq/vQRIQ
     [not found]       ` <1412070970-5625-3-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2014-09-30 11:23         ` Neil Horman
     [not found]           ` <20140930112353.GA2193-B26myB8xz7F8NnZeBjwnZQMhkBWG/bsMQH7oEaQurus@public.gmane.org>
2014-10-01  1:39             ` Tetsuya Mukawa
2014-10-01  4:27 ` [PATCH] Fix linking errors when CONFIG_RTE_BUILD_SHARED_LIB is enabled mukawa-AlSX/UN32fvPDbFq/vQRIQ
     [not found]   ` <1412137623-18817-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2014-10-01 10:50     ` Neil Horman
     [not found]       ` <20141001105022.GB21151-B26myB8xz7F8NnZeBjwnZQMhkBWG/bsMQH7oEaQurus@public.gmane.org>
2014-10-01 11:56         ` Thomas Monjalon
2014-10-02  2:48           ` Tetsuya Mukawa
     [not found]             ` <542CBD05.5000507-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2014-10-02  8:12               ` Sergio Gonzalez Monroy
     [not found]                 ` <20141002081221.GA27208-IWE99D/oH1/+pXziaqXtF9h3ngVCH38I@public.gmane.org>
2014-10-02  8:28                   ` Tetsuya Mukawa
     [not found]                     ` <542D0C94.70209-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2014-10-02  8:53                       ` Sergio Gonzalez Monroy
     [not found]                         ` <20141002085321.GA31287-IWE99D/oH1/+pXziaqXtF9h3ngVCH38I@public.gmane.org>
2014-10-02  9:05                           ` Tetsuya Mukawa
     [not found]                             ` <542D1545.8040202-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2014-10-03 11:11                               ` Sergio Gonzalez Monroy
2014-10-02  1:43         ` Tetsuya Mukawa
     [not found]           ` <542CADD8.9070402-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2014-10-02  2:46             ` Matthew Hall
     [not found]               ` <20141002024626.GA24668-Hv3ogNYU3JfZZajBQzqCxQ@public.gmane.org>
2014-10-02  3:44                 ` Tetsuya Mukawa
2014-10-01  4:57 ` [PATCH v2] PMD for performance measurement mukawa-AlSX/UN32fvPDbFq/vQRIQ
     [not found]   ` <1412139437-26749-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2014-10-01  4:57     ` [PATCH v2] librte_pmd_null: Add null PMD mukawa-AlSX/UN32fvPDbFq/vQRIQ
     [not found]       ` <1412139437-26749-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2014-11-13 12:17         ` Thomas Monjalon
2014-12-16  8:39         ` [PATCH v3] " Tetsuya Mukawa
     [not found]           ` <1418719167-8235-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2014-12-16  8:44             ` Tetsuya Mukawa
     [not found]               ` <548FF0EA.3010501-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2014-12-16  8:47                 ` Thomas Monjalon
2014-12-16  8:49                   ` Tetsuya Mukawa
2015-01-20  3:00             ` [PATCH v4 1/2] " Tetsuya Mukawa
     [not found]               ` <1421722821-18158-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2015-01-20  3:00                 ` [PATCH v4 2/2] librte_pmd_null: Support port hotplug function Tetsuya Mukawa
     [not found]                   ` <1421722821-18158-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2015-02-06  4:38                     ` [PATCH v6 1/2] librte_pmd_null: Add null PMD Tetsuya Mukawa
     [not found]                       ` <1423197495-1758-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2015-02-06  4:38                         ` [PATCH v6 2/2] librte_pmd_null: Support port hotplug function Tetsuya Mukawa
     [not found]                           ` <1423197495-1758-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2015-02-06 11:37                             ` Iremonger, Bernard
2015-02-06 11:32                         ` [PATCH v6 1/2] librte_pmd_null: Add null PMD Iremonger, Bernard
     [not found]                           ` <8CEF83825BEC744B83065625E567D7C2049DDE4A-kPTMFJFq+rEMvF1YICWikbfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2015-02-09  8:54                             ` Tetsuya Mukawa
2015-02-12  2:44                         ` [PATCH v7 1/2] librte_pmd_null: Add Null PMD Tetsuya Mukawa
     [not found]                           ` <1423709078-20999-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2015-02-12  2:44                             ` [PATCH v7 2/2] librte_pmd_null: Support port hotplug function Tetsuya Mukawa
2015-02-16  4:19                             ` [PATCH v8 1/2] librte_pmd_null: Add Null PMD Tetsuya Mukawa
     [not found]                             ` <1424060349-23693-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2015-02-16  4:19                               ` [PATCH v8 2/2] librte_pmd_null: Support port hotplug function Tetsuya Mukawa
     [not found]                                 ` <1424060349-23693-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2015-02-16 16:38                                   ` Iremonger, Bernard
2015-02-16 16:38                               ` [PATCH v8 1/2] librte_pmd_null: Add Null PMD Iremonger, Bernard
2015-02-19 10:41                               ` [PATCH v9 " Tetsuya Mukawa
     [not found]                                 ` <1424342510-1107-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2015-02-19 10:41                                   ` [PATCH v9 2/2] librte_pmd_null: Support port hotplug function Tetsuya Mukawa
2015-02-20  6:41                                   ` [PATCH v10 1/2] librte_pmd_null: Add Null PMD Tetsuya Mukawa
     [not found]                                     ` <1424414516-18609-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2015-02-20  6:41                                       ` [PATCH v10 2/2] librte_pmd_null: Support port hotplug function Tetsuya Mukawa
2015-02-23  5:12                                       ` [PATCH v11 1/2] librte_pmd_null: Add Null PMD Tetsuya Mukawa
     [not found]                                         ` <1424668355-8794-1-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2015-02-23  5:12                                           ` [PATCH v11 2/2] librte_pmd_null: Support port hotplug function Tetsuya Mukawa
     [not found]                                             ` <1424668355-8794-2-git-send-email-mukawa-AlSX/UN32fvPDbFq/vQRIQ@public.gmane.org>
2015-02-25 23:35                                               ` Thomas Monjalon
2015-02-26  0:49                                                 ` Stephen Hemminger
2015-02-26  7:03                                                   ` Thomas Monjalon
2015-02-26  9:06                                                     ` Tetsuya Mukawa
     [not found]                                                       ` <CAKU8wkcwLqHnHSx3qREXVcQJZQJpZ0rWtDu7We=kGM9iG4zjSA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-02-26 10:57                                                         ` Thomas Monjalon
2015-02-26 11:50                                                           ` Tetsuya Mukawa
2015-03-04  3:37                                                           ` Tetsuya Mukawa
2015-02-26 12:21                                                         ` Mcnamara, John
     [not found]                                                           ` <B27915DBBA3421428155699D51E4CFE2EC8A08-kPTMFJFq+rELt2AQoY/u9bfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2015-02-26 15:36                                                             ` Mcnamara, John
     [not found]                                                               ` <B27915DBBA3421428155699D51E4CFE2EC8B34-kPTMFJFq+rELt2AQoY/u9bfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2015-02-27  1:31                                                                 ` Tetsuya Mukawa
2015-02-27 23:29                                                             ` Thomas Monjalon

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.