List comments

GET /api/patches/431/comments/
HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[
    {
        "id": 888,
        "web_url": "http://patches.dpdk.org/comment/888/",
        "msgid": "<541FD3BD.2060606@6wind.com>",
        "date": "2014-09-22T07:46:05",
        "subject": "Re: [dpdk-dev] [RFC] librte_pmd_null: Add null PMD",
        "submitter": {
            "id": 21,
            "url": "http://patches.dpdk.org/api/people/21/",
            "name": "Ivan Boule",
            "email": "ivan.boule@6wind.com"
        },
        "content": "On 09/19/2014 02:27 PM, mukawa@igel.co.jp wrote:\n> From: Tetsuya Mukawa <mukawa@igel.co.jp>\n>\n> 'null PMD' is a virtual device driver particulary designed to measure\n> performance of DPDK applications and DPDK PMDs. When an application call rx,\n> null PMD just allocate mbufs and return those. Also tx, the PMD just free\n> mbufs.\n>\n> The PMD has following options.\n> - size: specify packe size allocated by RX. Default packet size is 64.\n> - copy: specify 1 or 0 to enable or disable copy while RX and TX.\n> \tDefault value is 0(disbaled).\n> \tThis option is used for emulating more realistic data transfer.\n> \tCopy size is equal to packet size.\nHi Tetsuya,\n\nThis is a \"nice to have\" PMD.\n\nJust a minor comment.\nI guess it should be NTT instead of Intel in the following comment\n\"#     * Neither the name of Intel Corporation nor the names of its\".\n\nRegards,\nIvan\n\n>\n> Signed-off-by: Tetsuya Mukawa <mukawa@igel.co.jp>\n> ---\n>   config/common_bsdapp               |   5 +\n>   config/common_linuxapp             |   5 +\n>   lib/Makefile                       |   1 +\n>   lib/librte_pmd_null/Makefile       |  58 +++++\n>   lib/librte_pmd_null/rte_eth_null.c | 474 +++++++++++++++++++++++++++++++++++++\n>   5 files changed, 543 insertions(+)\n>   create mode 100644 lib/librte_pmd_null/Makefile\n>   create mode 100644 lib/librte_pmd_null/rte_eth_null.c\n>\n> diff --git a/config/common_bsdapp b/config/common_bsdapp\n> index 645949f..a86321f 100644\n> --- a/config/common_bsdapp\n> +++ b/config/common_bsdapp\n> @@ -226,6 +226,11 @@ CONFIG_RTE_LIBRTE_PMD_PCAP=y\n>   CONFIG_RTE_LIBRTE_PMD_BOND=y\n>\n>   #\n> +# Compile null PMD\n> +#\n> +CONFIG_RTE_LIBRTE_PMD_NULL=y\n> +\n> +#\n>   # Do prefetch of packet data within PMD driver receive function\n>   #\n>   CONFIG_RTE_PMD_PACKET_PREFETCH=y\n> diff --git a/config/common_linuxapp b/config/common_linuxapp\n> index 5bee910..e3bd8c0 100644\n> --- a/config/common_linuxapp\n> +++ b/config/common_linuxapp\n> @@ -254,6 +254,11 @@ CONFIG_RTE_LIBRTE_PMD_BOND=y\n>   CONFIG_RTE_LIBRTE_PMD_XENVIRT=n\n>\n>   #\n> +# Compile null PMD\n> +#\n> +CONFIG_RTE_LIBRTE_PMD_NULL=y\n> +\n> +#\n>   # Do prefetch of packet data within PMD driver receive function\n>   #\n>   CONFIG_RTE_PMD_PACKET_PREFETCH=y\n> diff --git a/lib/Makefile b/lib/Makefile\n> index 10c5bb3..61d6ed1 100644\n> --- a/lib/Makefile\n> +++ b/lib/Makefile\n> @@ -50,6 +50,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += librte_pmd_pcap\n>   DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += librte_pmd_virtio\n>   DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3\n>   DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt\n> +DIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += librte_pmd_null\n>   DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash\n>   DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm\n>   DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl\n> diff --git a/lib/librte_pmd_null/Makefile b/lib/librte_pmd_null/Makefile\n> new file mode 100644\n> index 0000000..e017918\n> --- /dev/null\n> +++ b/lib/librte_pmd_null/Makefile\n> @@ -0,0 +1,58 @@\n> +#   BSD LICENSE\n> +#\n> +#   Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.\n> +#   All rights reserved.\n> +#\n> +#   Redistribution and use in source and binary forms, with or without\n> +#   modification, are permitted provided that the following conditions\n> +#   are met:\n> +#\n> +#     * Redistributions of source code must retain the above copyright\n> +#       notice, this list of conditions and the following disclaimer.\n> +#     * Redistributions in binary form must reproduce the above copyright\n> +#       notice, this list of conditions and the following disclaimer in\n> +#       the documentation and/or other materials provided with the\n> +#       distribution.\n> +#     * Neither the name of Intel Corporation nor the names of its\n> +#       contributors may be used to endorse or promote products derived\n> +#       from this software without specific prior written permission.\n> +#\n> +#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n> +#   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n> +#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n> +#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n> +#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n> +#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n> +#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n> +#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n> +#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n> +#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n> +#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n> +\n> +include $(RTE_SDK)/mk/rte.vars.mk\n> +\n> +#\n> +# library name\n> +#\n> +LIB = librte_pmd_null.a\n> +\n> +CFLAGS += -O3\n> +CFLAGS += $(WERROR_FLAGS)\n> +\n> +#\n> +# all source are stored in SRCS-y\n> +#\n> +SRCS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += rte_eth_null.c\n> +\n> +#\n> +# Export include files\n> +#\n> +SYMLINK-y-include +=\n> +\n> +# this lib depends upon:\n> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_mbuf\n> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_ether\n> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_malloc\n> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_kvargs\n> +\n> +include $(RTE_SDK)/mk/rte.lib.mk\n> diff --git a/lib/librte_pmd_null/rte_eth_null.c b/lib/librte_pmd_null/rte_eth_null.c\n> new file mode 100644\n> index 0000000..1a81843\n> --- /dev/null\n> +++ b/lib/librte_pmd_null/rte_eth_null.c\n> @@ -0,0 +1,474 @@\n> +/*-\n> + *   BSD LICENSE\n> + *\n> + *   Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.\n> + *   All rights reserved.\n> + *\n> + *   Redistribution and use in source and binary forms, with or without\n> + *   modification, are permitted provided that the following conditions\n> + *   are met:\n> + *\n> + *     * Redistributions of source code must retain the above copyright\n> + *       notice, this list of conditions and the following disclaimer.\n> + *     * Redistributions in binary form must reproduce the above copyright\n> + *       notice, this list of conditions and the following disclaimer in\n> + *       the documentation and/or other materials provided with the\n> + *       distribution.\n> + *     * Neither the name of Intel Corporation nor the names of its\n> + *       contributors may be used to endorse or promote products derived\n> + *       from this software without specific prior written permission.\n> + *\n> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n> + *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n> + */\n> +\n> +#include <rte_mbuf.h>\n> +#include <rte_ethdev.h>\n> +#include <rte_malloc.h>\n> +#include <rte_memcpy.h>\n> +#include <rte_dev.h>\n> +#include <rte_kvargs.h>\n> +\n> +#define ETH_NULL_PACKET_SIZE_ARG\t\"size\"\n> +#define ETH_NULL_PACKET_COPY_ARG\t\"copy\"\n> +\n> +static unsigned default_packet_size = 64;\n> +static unsigned default_packet_copy;\n> +\n> +static const char const *valid_arguments[] = {\n> +\tETH_NULL_PACKET_SIZE_ARG,\n> +\tETH_NULL_PACKET_COPY_ARG,\n> +\tNULL\n> +};\n> +\n> +struct pmd_internals;\n> +\n> +struct null_queue {\n> +\tstruct pmd_internals *internals;\n> +\n> +\tstruct rte_mempool *mb_pool;\n> +\tstruct rte_mbuf *dummy_packet;\n> +\n> +\trte_atomic64_t rx_pkts;\n> +\trte_atomic64_t tx_pkts;\n> +\trte_atomic64_t err_pkts;\n> +};\n> +\n> +struct pmd_internals {\n> +\tunsigned packet_size;\n> +\tunsigned packet_copy;\n> +\tunsigned numa_node;\n> +\n> +\tunsigned nb_rx_queues;\n> +\tunsigned nb_tx_queues;\n> +\n> +\tstruct null_queue rx_null_queues[1];\n> +\tstruct null_queue tx_null_queues[1];\n> +};\n> +\n> +\n> +static struct ether_addr eth_addr = { .addr_bytes = {0} };\n> +static const char *drivername = \"Null PMD\";\n> +static struct rte_eth_link pmd_link = {\n> +\t.link_speed = 10000,\n> +\t.link_duplex = ETH_LINK_FULL_DUPLEX,\n> +\t.link_status = 0\n> +};\n> +\n> +static uint16_t\n> +eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)\n> +{\n> +\tint i;\n> +\tstruct null_queue *h = q;\n> +\tunsigned packet_size = h->internals->packet_size;\n> +\n> +\tfor (i = 0; i < nb_bufs; i++) {\n> +\t\tbufs[i] = rte_pktmbuf_alloc(h->mb_pool);\n> +\t\tif (!bufs[i])\n> +\t\t\tbreak;\n> +\t\tbufs[i]->data_len = (uint16_t)packet_size;\n> +\t\tbufs[i]->pkt_len = packet_size;\n> +\t\tbufs[i]->nb_segs = 1;\n> +\t\tbufs[i]->next = NULL;\n> +\t}\n> +\n> +\trte_atomic64_add(&(h->rx_pkts), i);\n> +\n> +\treturn i;\n> +}\n> +\n> +static uint16_t\n> +eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)\n> +{\n> +\tint i;\n> +\tstruct null_queue *h = q;\n> +\tunsigned packet_size = h->internals->packet_size;\n> +\n> +\tfor (i = 0; i < nb_bufs; i++) {\n> +\t\tbufs[i] = rte_pktmbuf_alloc(h->mb_pool);\n> +\t\tif (!bufs[i])\n> +\t\t\tbreak;\n> +\t\trte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,\n> +\t\t\t\t\tpacket_size);\n> +\t\tbufs[i]->data_len = (uint16_t)packet_size;\n> +\t\tbufs[i]->pkt_len = packet_size;\n> +\t\tbufs[i]->nb_segs = 1;\n> +\t\tbufs[i]->next = NULL;\n> +\t}\n> +\n> +\trte_atomic64_add(&(h->rx_pkts), i);\n> +\n> +\treturn i;\n> +}\n> +\n> +static uint16_t\n> +eth_null_tx(void *q, struct rte_mbuf **bufs __rte_unused, uint16_t nb_bufs)\n> +{\n> +\tint i;\n> +\tstruct null_queue *h = q;\n> +\n> +\tfor (i = 0; i < nb_bufs; i++)\n> +\t\trte_pktmbuf_free(bufs[i]);\n> +\n> +\trte_atomic64_add(&(h->tx_pkts), i);\n> +\n> +\treturn i;\n> +}\n> +\n> +static uint16_t\n> +eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)\n> +{\n> +\tint i;\n> +\tstruct null_queue *h = q;\n> +\tunsigned packet_size = h->internals->packet_size;\n> +\n> +\tfor (i = 0; i < nb_bufs; i++) {\n> +\t\trte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *),\n> +\t\t\t\t\tpacket_size);\n> +\t\trte_pktmbuf_free(bufs[i]);\n> +\t}\n> +\n> +\trte_atomic64_add(&(h->tx_pkts), i);\n> +\n> +\treturn i;\n> +}\n> +\n> +static int\n> +eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; }\n> +\n> +static int\n> +eth_dev_start(struct rte_eth_dev *dev)\n> +{\n> +\tdev->data->dev_link.link_status = 1;\n> +\treturn 0;\n> +}\n> +\n> +static void\n> +eth_dev_stop(struct rte_eth_dev *dev)\n> +{\n> +\tdev->data->dev_link.link_status = 0;\n> +}\n> +\n> +static int\n> +eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,\n> +\t\tuint16_t nb_rx_desc __rte_unused,\n> +\t\tunsigned int socket_id __rte_unused,\n> +\t\tconst struct rte_eth_rxconf *rx_conf __rte_unused,\n> +\t\tstruct rte_mempool *mb_pool __rte_unused)\n> +{\n> +\tstruct rte_mbuf *dummy_packet;\n> +\tstruct pmd_internals *internals = dev->data->dev_private;\n> +\tunsigned packet_size = internals->packet_size;\n> +\n> +\tif (rx_queue_id != 0)\n> +\t\t\treturn -ENODEV;\n> +\n> +\tinternals->rx_null_queues[rx_queue_id].mb_pool = mb_pool;\n> +\tdev->data->rx_queues[rx_queue_id] =\n> +\t\t&internals->rx_null_queues[rx_queue_id];\n> +\tdummy_packet = rte_zmalloc_socket(NULL,\n> +\t\t\tpacket_size, 0, internals->numa_node);\n> +\tif (dummy_packet == NULL)\n> +\t\treturn -ENOMEM;\n> +\n> +\tinternals->rx_null_queues[rx_queue_id].internals = internals;\n> +\tinternals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet;\n> +\n> +\treturn 0;\n> +}\n> +\n> +static int\n> +eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,\n> +\t\tuint16_t nb_tx_desc __rte_unused,\n> +\t\tunsigned int socket_id __rte_unused,\n> +\t\tconst struct rte_eth_txconf *tx_conf __rte_unused)\n> +{\n> +\tstruct rte_mbuf *dummy_packet;\n> +\tstruct pmd_internals *internals = dev->data->dev_private;\n> +\tunsigned packet_size = internals->packet_size;\n> +\n> +\tif (tx_queue_id != 0)\n> +\t\t\treturn -ENODEV;\n> +\n> +\tdev->data->tx_queues[tx_queue_id] =\n> +\t\t&internals->tx_null_queues[tx_queue_id];\n> +\tdummy_packet = rte_zmalloc_socket(NULL,\n> +\t\t\tpacket_size, 0, internals->numa_node);\n> +\tif (dummy_packet == NULL)\n> +\t\treturn -ENOMEM;\n> +\n> +\tinternals->tx_null_queues[tx_queue_id].internals = internals;\n> +\tinternals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet;\n> +\n> +\treturn 0;\n> +}\n> +\n> +\n> +static void\n> +eth_dev_info(struct rte_eth_dev *dev,\n> +\t\tstruct rte_eth_dev_info *dev_info)\n> +{\n> +\tstruct pmd_internals *internals = dev->data->dev_private;\n> +\n> +\tdev_info->driver_name = drivername;\n> +\tdev_info->max_mac_addrs = 1;\n> +\tdev_info->max_rx_pktlen = (uint32_t)-1;\n> +\tdev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;\n> +\tdev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;\n> +\tdev_info->min_rx_bufsize = 0;\n> +\tdev_info->pci_dev = NULL;\n> +}\n> +\n> +static void\n> +eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)\n> +{\n> +\tunsigned i;\n> +\tunsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;\n> +\tconst struct pmd_internals *internal = dev->data->dev_private;\n> +\n> +\tmemset(igb_stats, 0, sizeof(*igb_stats));\n> +\tfor (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&\n> +\t\t\ti < internal->nb_rx_queues; i++) {\n> +\t\tigb_stats->q_ipackets[i] =\n> +\t\t\tinternal->rx_null_queues[i].rx_pkts.cnt;\n> +\t\trx_total += igb_stats->q_ipackets[i];\n> +\t}\n> +\n> +\tfor (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&\n> +\t\t\ti < internal->nb_tx_queues; i++) {\n> +\t\tigb_stats->q_opackets[i] =\n> +\t\t\tinternal->tx_null_queues[i].tx_pkts.cnt;\n> +\t\tigb_stats->q_errors[i] =\n> +\t\t\tinternal->tx_null_queues[i].err_pkts.cnt;\n> +\t\ttx_total += igb_stats->q_opackets[i];\n> +\t\ttx_err_total += igb_stats->q_errors[i];\n> +\t}\n> +\n> +\tigb_stats->ipackets = rx_total;\n> +\tigb_stats->opackets = tx_total;\n> +\tigb_stats->oerrors = tx_err_total;\n> +}\n> +\n> +static void\n> +eth_stats_reset(struct rte_eth_dev *dev)\n> +{\n> +\tunsigned i;\n> +\tstruct pmd_internals *internal = dev->data->dev_private;\n> +\n> +\tfor (i = 0; i < internal->nb_rx_queues; i++)\n> +\t\tinternal->rx_null_queues[i].rx_pkts.cnt = 0;\n> +\tfor (i = 0; i < internal->nb_tx_queues; i++) {\n> +\t\tinternal->tx_null_queues[i].tx_pkts.cnt = 0;\n> +\t\tinternal->tx_null_queues[i].err_pkts.cnt = 0;\n> +\t}\n> +}\n> +\n> +static void\n> +eth_queue_release(void *q __rte_unused) { ; }\n> +static int\n> +eth_link_update(struct rte_eth_dev *dev __rte_unused,\n> +\t\tint wait_to_complete __rte_unused) { return 0; }\n> +\n> +static struct eth_dev_ops ops = {\n> +\t\t.dev_start = eth_dev_start,\n> +\t\t.dev_stop = eth_dev_stop,\n> +\t\t.dev_configure = eth_dev_configure,\n> +\t\t.dev_infos_get = eth_dev_info,\n> +\t\t.rx_queue_setup = eth_rx_queue_setup,\n> +\t\t.tx_queue_setup = eth_tx_queue_setup,\n> +\t\t.rx_queue_release = eth_queue_release,\n> +\t\t.tx_queue_release = eth_queue_release,\n> +\t\t.link_update = eth_link_update,\n> +\t\t.stats_get = eth_stats_get,\n> +\t\t.stats_reset = eth_stats_reset,\n> +};\n> +\n> +static int\n> +eth_dev_null_create(const char *name __rte_unused,\n> +\t\tconst unsigned numa_node,\n> +\t\tunsigned packet_size,\n> +\t\tunsigned packet_copy)\n> +{\n> +\tconst unsigned nb_rx_queues = 1;\n> +\tconst unsigned nb_tx_queues = 1;\n> +\tstruct rte_eth_dev_data *data = NULL;\n> +\tstruct rte_pci_device *pci_dev = NULL;\n> +\tstruct pmd_internals *internals = NULL;\n> +\tstruct rte_eth_dev *eth_dev = NULL;\n> +\n> +\tRTE_LOG(INFO, PMD, \"Creating null ethdev on numa socket %u\\n\",\n> +\t\t\tnuma_node);\n> +\n> +\t/* now do all data allocation - for eth_dev structure, dummy pci driver\n> +\t * and internal (private) data\n> +\t */\n> +\tdata = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);\n> +\tif (data == NULL)\n> +\t\tgoto error;\n> +\n> +\tpci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);\n> +\tif (pci_dev == NULL)\n> +\t\tgoto error;\n> +\n> +\tinternals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node);\n> +\tif (internals == NULL)\n> +\t\tgoto error;\n> +\n> +\t/* reserve an ethdev entry */\n> +\teth_dev = rte_eth_dev_allocate(name);\n> +\tif (eth_dev == NULL)\n> +\t\tgoto error;\n> +\n> +\t/* now put it all together\n> +\t * - store queue data in internals,\n> +\t * - store numa_node info in pci_driver\n> +\t * - point eth_dev_data to internals and pci_driver\n> +\t * - and point eth_dev structure to new eth_dev_data structure\n> +\t */\n> +\t/* NOTE: we'll replace the data element, of originally allocated eth_dev\n> +\t * so the nulls are local per-process */\n> +\n> +\tinternals->nb_rx_queues = nb_rx_queues;\n> +\tinternals->nb_tx_queues = nb_tx_queues;\n> +\tinternals->packet_size = packet_size;\n> +\tinternals->packet_copy = packet_copy;\n> +\tinternals->numa_node = numa_node;\n> +\n> +\tpci_dev->numa_node = numa_node;\n> +\n> +\tdata->dev_private = internals;\n> +\tdata->port_id = eth_dev->data->port_id;\n> +\tdata->nb_rx_queues = (uint16_t)nb_rx_queues;\n> +\tdata->nb_tx_queues = (uint16_t)nb_tx_queues;\n> +\tdata->dev_link = pmd_link;\n> +\tdata->mac_addrs = &eth_addr;\n> +\n> +\teth_dev->data = data;\n> +\teth_dev->dev_ops = &ops;\n> +\teth_dev->pci_dev = pci_dev;\n> +\n> +\t/* finally assign rx and tx ops */\n> +\tif (packet_copy) {\n> +\t\teth_dev->rx_pkt_burst = eth_null_copy_rx;\n> +\t\teth_dev->tx_pkt_burst = eth_null_copy_tx;\n> +\t} else {\n> +\t\teth_dev->rx_pkt_burst = eth_null_rx;\n> +\t\teth_dev->tx_pkt_burst = eth_null_tx;\n> +\t}\n> +\n> +\treturn 0;\n> +\n> +error:\n> +\tif (data)\n> +\t\trte_free(data);\n> +\tif (pci_dev)\n> +\t\trte_free(pci_dev);\n> +\tif (internals)\n> +\t\trte_free(internals);\n> +\treturn -1;\n> +}\n> +\n> +static inline int\n> +get_packet_size_arg(const char *key __rte_unused,\n> +\t\tconst char *value, void *extra_args)\n> +{\n> +\tconst char *a = value;\n> +\tunsigned *packet_size = extra_args;\n> +\n> +\t*packet_size = (unsigned)strtoul(a, NULL, 0);\n> +\tif (*packet_size == UINT_MAX)\n> +\t\treturn -1;\n> +\n> +\treturn 0;\n> +}\n> +\n> +static inline int\n> +get_packet_copy_arg(const char *key __rte_unused,\n> +\t\tconst char *value, void *extra_args)\n> +{\n> +\tconst char *a = value;\n> +\tunsigned *packet_copy = extra_args;\n> +\n> +\t*packet_copy = (unsigned)strtoul(a, NULL, 0);\n> +\tif (*packet_copy == UINT_MAX)\n> +\t\treturn -1;\n> +\n> +\treturn 0;\n> +}\n> +\n> +static int\n> +rte_pmd_null_devinit(const char *name, const char *params)\n> +{\n> +\tunsigned numa_node;\n> +\tunsigned packet_size = default_packet_size;\n> +\tunsigned packet_copy = default_packet_copy;\n> +\tstruct rte_kvargs *kvlist;\n> +\tint ret;\n> +\n> +\tRTE_LOG(INFO, PMD, \"Initializing pmd_null for %s\\n\", name);\n> +\n> +\tnuma_node = rte_socket_id();\n> +\n> +\tkvlist = rte_kvargs_parse(params, valid_arguments);\n> +\tif (kvlist == NULL)\n> +\t\treturn -1;\n> +\n> +\tif (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) {\n> +\n> +\t\tret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_SIZE_ARG,\n> +\t\t\t\t&get_packet_size_arg, &packet_size);\n> +\t\tif (ret < 0)\n> +\t\t\treturn -1;\n> +\t}\n> +\n> +\tif (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) {\n> +\n> +\t\tret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_COPY_ARG,\n> +\t\t\t\t&get_packet_copy_arg, &packet_copy);\n> +\t\tif (ret < 0)\n> +\t\t\treturn -1;\n> +\t}\n> +\n> +\tRTE_LOG(INFO, PMD, \"Configure pmd_null: packet size is %d, \"\n> +\t\t\t\"packet copy is %s\\n\", packet_size,\n> +\t\t\tpacket_copy ? \"enabled\" : \"disabled\");\n> +\n> +\treturn eth_dev_null_create(name, numa_node, packet_size, packet_copy);\n> +}\n> +\n> +static struct rte_driver pmd_null_drv = {\n> +\t.name = \"eth_null\",\n> +\t.type = PMD_VDEV,\n> +\t.init = rte_pmd_null_devinit,\n> +};\n> +\n> +PMD_REGISTER_DRIVER(pmd_null_drv);\n>",
        "headers": {
            "Return-Path": "<dev-bounces@dpdk.org>",
            "MIME-Version": "1.0",
            "X-Mailman-Version": "2.1.15",
            "From": "Ivan Boule <ivan.boule@6wind.com>",
            "User-Agent": "Mozilla/5.0 (X11; Linux x86_64;\n\trv:24.0) Gecko/20100101 Icedove/24.7.0",
            "List-Post": "<mailto:dev@dpdk.org>",
            "X-BeenThere": "dev@dpdk.org",
            "Content-Type": "text/plain; charset=ISO-8859-1; format=flowed",
            "References": "<mukawa@igel.co.jp>\n\t<1411129659-7132-1-git-send-email-mukawa@igel.co.jp>\n\t<1411129659-7132-2-git-send-email-mukawa@igel.co.jp>",
            "X-Original-To": "patchwork@dpdk.org",
            "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20130820;\n\th=x-gm-message-state:message-id:date:from:user-agent:mime-version:to\n\t:cc:subject:references:in-reply-to:content-type\n\t:content-transfer-encoding;\n\tbh=WiQOC7z8tVwjClW5Uyzvnf+wGQXubYDk4EWup7+0Xmc=;\n\tb=kRX1VH25UPYibLgDTGuApUd8OSGyATPd3IsMTzmW6gsyWUNDy6KGYdaJvZw8Gbd230\n\tCH/8JpQ2WtRklSE1IM7Gu70+LkxDNNE0vP8CQDrJYKnLtYZAsFgbP8B/OPos8rqi9/gj\n\t52XW0/rsvuV4YJ3/FFRnbV+gyFwoO/bI/5vlTs0czQSUBSURk+cFuTYsZlS96X7tavSb\n\tf/eMAEoDLgwTSSC1uzPdx8/GZsesGjxOTYpRInppk4/kN2WwRB69ztfgc0pXSDSgj+Ny\n\tpWzVMuQwP5nUe3QgnE+/55AV79QXs04RhBgjJBNu9O8e8h9UABhcc2QW4SWHlV0/vWK6\n\tfybw==",
            "Received": [
                "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 66FE22E81;\n\tMon, 22 Sep 2014 09:40:01 +0200 (CEST)",
                "from mail-wi0-f173.google.com (mail-wi0-f173.google.com\n\t[209.85.212.173]) by dpdk.org (Postfix) with ESMTP id DED02231C\n\tfor <dev@dpdk.org>; Mon, 22 Sep 2014 09:40:00 +0200 (CEST)",
                "by mail-wi0-f173.google.com with SMTP id r20so2348396wiv.12\n\tfor <dev@dpdk.org>; Mon, 22 Sep 2014 00:46:03 -0700 (PDT)",
                "from [10.16.0.189] (guy78-3-82-239-227-177.fbx.proxad.net.\n\t[82.239.227.177]) by mx.google.com with ESMTPSA id\n\tu5sm11116877wia.17.2014.09.22.00.46.02 for <multiple recipients>\n\t(version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128);\n\tMon, 22 Sep 2014 00:46:02 -0700 (PDT)"
            ],
            "Subject": "Re: [dpdk-dev] [RFC] librte_pmd_null: Add null PMD",
            "X-Received": "by 10.180.86.225 with SMTP id s1mr5385692wiz.21.1411371963610;\n\tMon, 22 Sep 2014 00:46:03 -0700 (PDT)",
            "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
            "Message-ID": "<541FD3BD.2060606@6wind.com>",
            "Precedence": "list",
            "X-Gm-Message-State": "ALoCoQlxQ9iXD6FdqsB4cMlwdy4VAvdy1ZDm+Jf3R3pIEoUvZfEXw5aJp/3HYNlPGFzuP4uFVbaH",
            "Date": "Mon, 22 Sep 2014 09:46:05 +0200",
            "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
            "Sender": "\"dev\" <dev-bounces@dpdk.org>",
            "Errors-To": "dev-bounces@dpdk.org",
            "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
            "Cc": "nakajima.yoshihiro@lab.ntt.co.jp, masutani.hitoshi@lab.ntt.co.jp",
            "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
            "Delivered-To": "patchwork@dpdk.org",
            "In-Reply-To": "<1411129659-7132-2-git-send-email-mukawa@igel.co.jp>",
            "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
            "Content-Transfer-Encoding": "7bit",
            "To": "mukawa@igel.co.jp, dev@dpdk.org"
        }
    },
    {
        "id": 889,
        "web_url": "http://patches.dpdk.org/comment/889/",
        "msgid": "<541FD8CA.7060500@igel.co.jp>",
        "date": "2014-09-22T08:07:38",
        "subject": "Re: [dpdk-dev] [RFC] librte_pmd_null: Add null PMD",
        "submitter": {
            "id": 64,
            "url": "http://patches.dpdk.org/api/people/64/",
            "name": "Tetsuya Mukawa",
            "email": "mukawa@igel.co.jp"
        },
        "content": "Hi Ivan\n\n(2014/09/22 16:46), Ivan Boule wrote:\n>\n> This is a \"nice to have\" PMD.\n>\n> Just a minor comment.\n> I guess it should be NTT instead of Intel in the following comment\n> \"#     * Neither the name of Intel Corporation nor the names of its\".\n>\nI appreciate your comment. I will rewrite and post it again.\n\nRegards,\nTetsuya\n\n\n> Regards,\n> Ivan\n>\n>>\n>> Signed-off-by: Tetsuya Mukawa <mukawa@igel.co.jp>\n>> ---\n>>   config/common_bsdapp               |   5 +\n>>   config/common_linuxapp             |   5 +\n>>   lib/Makefile                       |   1 +\n>>   lib/librte_pmd_null/Makefile       |  58 +++++\n>>   lib/librte_pmd_null/rte_eth_null.c | 474\n>> +++++++++++++++++++++++++++++++++++++\n>>   5 files changed, 543 insertions(+)\n>>   create mode 100644 lib/librte_pmd_null/Makefile\n>>   create mode 100644 lib/librte_pmd_null/rte_eth_null.c\n>>\n>> diff --git a/config/common_bsdapp b/config/common_bsdapp\n>> index 645949f..a86321f 100644\n>> --- a/config/common_bsdapp\n>> +++ b/config/common_bsdapp\n>> @@ -226,6 +226,11 @@ CONFIG_RTE_LIBRTE_PMD_PCAP=y\n>>   CONFIG_RTE_LIBRTE_PMD_BOND=y\n>>\n>>   #\n>> +# Compile null PMD\n>> +#\n>> +CONFIG_RTE_LIBRTE_PMD_NULL=y\n>> +\n>> +#\n>>   # Do prefetch of packet data within PMD driver receive function\n>>   #\n>>   CONFIG_RTE_PMD_PACKET_PREFETCH=y\n>> diff --git a/config/common_linuxapp b/config/common_linuxapp\n>> index 5bee910..e3bd8c0 100644\n>> --- a/config/common_linuxapp\n>> +++ b/config/common_linuxapp\n>> @@ -254,6 +254,11 @@ CONFIG_RTE_LIBRTE_PMD_BOND=y\n>>   CONFIG_RTE_LIBRTE_PMD_XENVIRT=n\n>>\n>>   #\n>> +# Compile null PMD\n>> +#\n>> +CONFIG_RTE_LIBRTE_PMD_NULL=y\n>> +\n>> +#\n>>   # Do prefetch of packet data within PMD driver receive function\n>>   #\n>>   CONFIG_RTE_PMD_PACKET_PREFETCH=y\n>> diff --git a/lib/Makefile b/lib/Makefile\n>> index 10c5bb3..61d6ed1 100644\n>> --- a/lib/Makefile\n>> +++ b/lib/Makefile\n>> @@ -50,6 +50,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += librte_pmd_pcap\n>>   DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += librte_pmd_virtio\n>>   DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += librte_pmd_vmxnet3\n>>   DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += librte_pmd_xenvirt\n>> +DIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += librte_pmd_null\n>>   DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash\n>>   DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm\n>>   DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl\n>> diff --git a/lib/librte_pmd_null/Makefile b/lib/librte_pmd_null/Makefile\n>> new file mode 100644\n>> index 0000000..e017918\n>> --- /dev/null\n>> +++ b/lib/librte_pmd_null/Makefile\n>> @@ -0,0 +1,58 @@\n>> +#   BSD LICENSE\n>> +#\n>> +#   Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.\n>> +#   All rights reserved.\n>> +#\n>> +#   Redistribution and use in source and binary forms, with or without\n>> +#   modification, are permitted provided that the following conditions\n>> +#   are met:\n>> +#\n>> +#     * Redistributions of source code must retain the above copyright\n>> +#       notice, this list of conditions and the following disclaimer.\n>> +#     * Redistributions in binary form must reproduce the above\n>> copyright\n>> +#       notice, this list of conditions and the following disclaimer in\n>> +#       the documentation and/or other materials provided with the\n>> +#       distribution.\n>> +#     * Neither the name of Intel Corporation nor the names of its\n>> +#       contributors may be used to endorse or promote products derived\n>> +#       from this software without specific prior written permission.\n>> +#\n>> +#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n>> +#   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n>> +#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n>> FITNESS FOR\n>> +#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n>> COPYRIGHT\n>> +#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n>> INCIDENTAL,\n>> +#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n>> +#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF\n>> USE,\n>> +#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n>> ON ANY\n>> +#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n>> +#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\n>> THE USE\n>> +#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\n>> DAMAGE.\n>> +\n>> +include $(RTE_SDK)/mk/rte.vars.mk\n>> +\n>> +#\n>> +# library name\n>> +#\n>> +LIB = librte_pmd_null.a\n>> +\n>> +CFLAGS += -O3\n>> +CFLAGS += $(WERROR_FLAGS)\n>> +\n>> +#\n>> +# all source are stored in SRCS-y\n>> +#\n>> +SRCS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += rte_eth_null.c\n>> +\n>> +#\n>> +# Export include files\n>> +#\n>> +SYMLINK-y-include +=\n>> +\n>> +# this lib depends upon:\n>> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_mbuf\n>> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_ether\n>> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_malloc\n>> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_kvargs\n>> +\n>> +include $(RTE_SDK)/mk/rte.lib.mk\n>> diff --git a/lib/librte_pmd_null/rte_eth_null.c\n>> b/lib/librte_pmd_null/rte_eth_null.c\n>> new file mode 100644\n>> index 0000000..1a81843\n>> --- /dev/null\n>> +++ b/lib/librte_pmd_null/rte_eth_null.c\n>> @@ -0,0 +1,474 @@\n>> +/*-\n>> + *   BSD LICENSE\n>> + *\n>> + *   Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.\n>> + *   All rights reserved.\n>> + *\n>> + *   Redistribution and use in source and binary forms, with or without\n>> + *   modification, are permitted provided that the following conditions\n>> + *   are met:\n>> + *\n>> + *     * Redistributions of source code must retain the above copyright\n>> + *       notice, this list of conditions and the following disclaimer.\n>> + *     * Redistributions in binary form must reproduce the above\n>> copyright\n>> + *       notice, this list of conditions and the following\n>> disclaimer in\n>> + *       the documentation and/or other materials provided with the\n>> + *       distribution.\n>> + *     * Neither the name of Intel Corporation nor the names of its\n>> + *       contributors may be used to endorse or promote products\n>> derived\n>> + *       from this software without specific prior written permission.\n>> + *\n>> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n>> CONTRIBUTORS\n>> + *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n>> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n>> FITNESS FOR\n>> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n>> COPYRIGHT\n>> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n>> INCIDENTAL,\n>> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n>> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS\n>> OF USE,\n>> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n>> ON ANY\n>> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\n>> TORT\n>> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\n>> THE USE\n>> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\n>> DAMAGE.\n>> + */\n>> +\n>> +#include <rte_mbuf.h>\n>> +#include <rte_ethdev.h>\n>> +#include <rte_malloc.h>\n>> +#include <rte_memcpy.h>\n>> +#include <rte_dev.h>\n>> +#include <rte_kvargs.h>\n>> +\n>> +#define ETH_NULL_PACKET_SIZE_ARG    \"size\"\n>> +#define ETH_NULL_PACKET_COPY_ARG    \"copy\"\n>> +\n>> +static unsigned default_packet_size = 64;\n>> +static unsigned default_packet_copy;\n>> +\n>> +static const char const *valid_arguments[] = {\n>> +    ETH_NULL_PACKET_SIZE_ARG,\n>> +    ETH_NULL_PACKET_COPY_ARG,\n>> +    NULL\n>> +};\n>> +\n>> +struct pmd_internals;\n>> +\n>> +struct null_queue {\n>> +    struct pmd_internals *internals;\n>> +\n>> +    struct rte_mempool *mb_pool;\n>> +    struct rte_mbuf *dummy_packet;\n>> +\n>> +    rte_atomic64_t rx_pkts;\n>> +    rte_atomic64_t tx_pkts;\n>> +    rte_atomic64_t err_pkts;\n>> +};\n>> +\n>> +struct pmd_internals {\n>> +    unsigned packet_size;\n>> +    unsigned packet_copy;\n>> +    unsigned numa_node;\n>> +\n>> +    unsigned nb_rx_queues;\n>> +    unsigned nb_tx_queues;\n>> +\n>> +    struct null_queue rx_null_queues[1];\n>> +    struct null_queue tx_null_queues[1];\n>> +};\n>> +\n>> +\n>> +static struct ether_addr eth_addr = { .addr_bytes = {0} };\n>> +static const char *drivername = \"Null PMD\";\n>> +static struct rte_eth_link pmd_link = {\n>> +    .link_speed = 10000,\n>> +    .link_duplex = ETH_LINK_FULL_DUPLEX,\n>> +    .link_status = 0\n>> +};\n>> +\n>> +static uint16_t\n>> +eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)\n>> +{\n>> +    int i;\n>> +    struct null_queue *h = q;\n>> +    unsigned packet_size = h->internals->packet_size;\n>> +\n>> +    for (i = 0; i < nb_bufs; i++) {\n>> +        bufs[i] = rte_pktmbuf_alloc(h->mb_pool);\n>> +        if (!bufs[i])\n>> +            break;\n>> +        bufs[i]->data_len = (uint16_t)packet_size;\n>> +        bufs[i]->pkt_len = packet_size;\n>> +        bufs[i]->nb_segs = 1;\n>> +        bufs[i]->next = NULL;\n>> +    }\n>> +\n>> +    rte_atomic64_add(&(h->rx_pkts), i);\n>> +\n>> +    return i;\n>> +}\n>> +\n>> +static uint16_t\n>> +eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)\n>> +{\n>> +    int i;\n>> +    struct null_queue *h = q;\n>> +    unsigned packet_size = h->internals->packet_size;\n>> +\n>> +    for (i = 0; i < nb_bufs; i++) {\n>> +        bufs[i] = rte_pktmbuf_alloc(h->mb_pool);\n>> +        if (!bufs[i])\n>> +            break;\n>> +        rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,\n>> +                    packet_size);\n>> +        bufs[i]->data_len = (uint16_t)packet_size;\n>> +        bufs[i]->pkt_len = packet_size;\n>> +        bufs[i]->nb_segs = 1;\n>> +        bufs[i]->next = NULL;\n>> +    }\n>> +\n>> +    rte_atomic64_add(&(h->rx_pkts), i);\n>> +\n>> +    return i;\n>> +}\n>> +\n>> +static uint16_t\n>> +eth_null_tx(void *q, struct rte_mbuf **bufs __rte_unused, uint16_t\n>> nb_bufs)\n>> +{\n>> +    int i;\n>> +    struct null_queue *h = q;\n>> +\n>> +    for (i = 0; i < nb_bufs; i++)\n>> +        rte_pktmbuf_free(bufs[i]);\n>> +\n>> +    rte_atomic64_add(&(h->tx_pkts), i);\n>> +\n>> +    return i;\n>> +}\n>> +\n>> +static uint16_t\n>> +eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)\n>> +{\n>> +    int i;\n>> +    struct null_queue *h = q;\n>> +    unsigned packet_size = h->internals->packet_size;\n>> +\n>> +    for (i = 0; i < nb_bufs; i++) {\n>> +        rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *),\n>> +                    packet_size);\n>> +        rte_pktmbuf_free(bufs[i]);\n>> +    }\n>> +\n>> +    rte_atomic64_add(&(h->tx_pkts), i);\n>> +\n>> +    return i;\n>> +}\n>> +\n>> +static int\n>> +eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; }\n>> +\n>> +static int\n>> +eth_dev_start(struct rte_eth_dev *dev)\n>> +{\n>> +    dev->data->dev_link.link_status = 1;\n>> +    return 0;\n>> +}\n>> +\n>> +static void\n>> +eth_dev_stop(struct rte_eth_dev *dev)\n>> +{\n>> +    dev->data->dev_link.link_status = 0;\n>> +}\n>> +\n>> +static int\n>> +eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,\n>> +        uint16_t nb_rx_desc __rte_unused,\n>> +        unsigned int socket_id __rte_unused,\n>> +        const struct rte_eth_rxconf *rx_conf __rte_unused,\n>> +        struct rte_mempool *mb_pool __rte_unused)\n>> +{\n>> +    struct rte_mbuf *dummy_packet;\n>> +    struct pmd_internals *internals = dev->data->dev_private;\n>> +    unsigned packet_size = internals->packet_size;\n>> +\n>> +    if (rx_queue_id != 0)\n>> +            return -ENODEV;\n>> +\n>> +    internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool;\n>> +    dev->data->rx_queues[rx_queue_id] =\n>> +        &internals->rx_null_queues[rx_queue_id];\n>> +    dummy_packet = rte_zmalloc_socket(NULL,\n>> +            packet_size, 0, internals->numa_node);\n>> +    if (dummy_packet == NULL)\n>> +        return -ENOMEM;\n>> +\n>> +    internals->rx_null_queues[rx_queue_id].internals = internals;\n>> +    internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet;\n>> +\n>> +    return 0;\n>> +}\n>> +\n>> +static int\n>> +eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,\n>> +        uint16_t nb_tx_desc __rte_unused,\n>> +        unsigned int socket_id __rte_unused,\n>> +        const struct rte_eth_txconf *tx_conf __rte_unused)\n>> +{\n>> +    struct rte_mbuf *dummy_packet;\n>> +    struct pmd_internals *internals = dev->data->dev_private;\n>> +    unsigned packet_size = internals->packet_size;\n>> +\n>> +    if (tx_queue_id != 0)\n>> +            return -ENODEV;\n>> +\n>> +    dev->data->tx_queues[tx_queue_id] =\n>> +        &internals->tx_null_queues[tx_queue_id];\n>> +    dummy_packet = rte_zmalloc_socket(NULL,\n>> +            packet_size, 0, internals->numa_node);\n>> +    if (dummy_packet == NULL)\n>> +        return -ENOMEM;\n>> +\n>> +    internals->tx_null_queues[tx_queue_id].internals = internals;\n>> +    internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet;\n>> +\n>> +    return 0;\n>> +}\n>> +\n>> +\n>> +static void\n>> +eth_dev_info(struct rte_eth_dev *dev,\n>> +        struct rte_eth_dev_info *dev_info)\n>> +{\n>> +    struct pmd_internals *internals = dev->data->dev_private;\n>> +\n>> +    dev_info->driver_name = drivername;\n>> +    dev_info->max_mac_addrs = 1;\n>> +    dev_info->max_rx_pktlen = (uint32_t)-1;\n>> +    dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues;\n>> +    dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues;\n>> +    dev_info->min_rx_bufsize = 0;\n>> +    dev_info->pci_dev = NULL;\n>> +}\n>> +\n>> +static void\n>> +eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)\n>> +{\n>> +    unsigned i;\n>> +    unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;\n>> +    const struct pmd_internals *internal = dev->data->dev_private;\n>> +\n>> +    memset(igb_stats, 0, sizeof(*igb_stats));\n>> +    for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&\n>> +            i < internal->nb_rx_queues; i++) {\n>> +        igb_stats->q_ipackets[i] =\n>> +            internal->rx_null_queues[i].rx_pkts.cnt;\n>> +        rx_total += igb_stats->q_ipackets[i];\n>> +    }\n>> +\n>> +    for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&\n>> +            i < internal->nb_tx_queues; i++) {\n>> +        igb_stats->q_opackets[i] =\n>> +            internal->tx_null_queues[i].tx_pkts.cnt;\n>> +        igb_stats->q_errors[i] =\n>> +            internal->tx_null_queues[i].err_pkts.cnt;\n>> +        tx_total += igb_stats->q_opackets[i];\n>> +        tx_err_total += igb_stats->q_errors[i];\n>> +    }\n>> +\n>> +    igb_stats->ipackets = rx_total;\n>> +    igb_stats->opackets = tx_total;\n>> +    igb_stats->oerrors = tx_err_total;\n>> +}\n>> +\n>> +static void\n>> +eth_stats_reset(struct rte_eth_dev *dev)\n>> +{\n>> +    unsigned i;\n>> +    struct pmd_internals *internal = dev->data->dev_private;\n>> +\n>> +    for (i = 0; i < internal->nb_rx_queues; i++)\n>> +        internal->rx_null_queues[i].rx_pkts.cnt = 0;\n>> +    for (i = 0; i < internal->nb_tx_queues; i++) {\n>> +        internal->tx_null_queues[i].tx_pkts.cnt = 0;\n>> +        internal->tx_null_queues[i].err_pkts.cnt = 0;\n>> +    }\n>> +}\n>> +\n>> +static void\n>> +eth_queue_release(void *q __rte_unused) { ; }\n>> +static int\n>> +eth_link_update(struct rte_eth_dev *dev __rte_unused,\n>> +        int wait_to_complete __rte_unused) { return 0; }\n>> +\n>> +static struct eth_dev_ops ops = {\n>> +        .dev_start = eth_dev_start,\n>> +        .dev_stop = eth_dev_stop,\n>> +        .dev_configure = eth_dev_configure,\n>> +        .dev_infos_get = eth_dev_info,\n>> +        .rx_queue_setup = eth_rx_queue_setup,\n>> +        .tx_queue_setup = eth_tx_queue_setup,\n>> +        .rx_queue_release = eth_queue_release,\n>> +        .tx_queue_release = eth_queue_release,\n>> +        .link_update = eth_link_update,\n>> +        .stats_get = eth_stats_get,\n>> +        .stats_reset = eth_stats_reset,\n>> +};\n>> +\n>> +static int\n>> +eth_dev_null_create(const char *name __rte_unused,\n>> +        const unsigned numa_node,\n>> +        unsigned packet_size,\n>> +        unsigned packet_copy)\n>> +{\n>> +    const unsigned nb_rx_queues = 1;\n>> +    const unsigned nb_tx_queues = 1;\n>> +    struct rte_eth_dev_data *data = NULL;\n>> +    struct rte_pci_device *pci_dev = NULL;\n>> +    struct pmd_internals *internals = NULL;\n>> +    struct rte_eth_dev *eth_dev = NULL;\n>> +\n>> +    RTE_LOG(INFO, PMD, \"Creating null ethdev on numa socket %u\\n\",\n>> +            numa_node);\n>> +\n>> +    /* now do all data allocation - for eth_dev structure, dummy pci\n>> driver\n>> +     * and internal (private) data\n>> +     */\n>> +    data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);\n>> +    if (data == NULL)\n>> +        goto error;\n>> +\n>> +    pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);\n>> +    if (pci_dev == NULL)\n>> +        goto error;\n>> +\n>> +    internals = rte_zmalloc_socket(name, sizeof(*internals), 0,\n>> numa_node);\n>> +    if (internals == NULL)\n>> +        goto error;\n>> +\n>> +    /* reserve an ethdev entry */\n>> +    eth_dev = rte_eth_dev_allocate(name);\n>> +    if (eth_dev == NULL)\n>> +        goto error;\n>> +\n>> +    /* now put it all together\n>> +     * - store queue data in internals,\n>> +     * - store numa_node info in pci_driver\n>> +     * - point eth_dev_data to internals and pci_driver\n>> +     * - and point eth_dev structure to new eth_dev_data structure\n>> +     */\n>> +    /* NOTE: we'll replace the data element, of originally allocated\n>> eth_dev\n>> +     * so the nulls are local per-process */\n>> +\n>> +    internals->nb_rx_queues = nb_rx_queues;\n>> +    internals->nb_tx_queues = nb_tx_queues;\n>> +    internals->packet_size = packet_size;\n>> +    internals->packet_copy = packet_copy;\n>> +    internals->numa_node = numa_node;\n>> +\n>> +    pci_dev->numa_node = numa_node;\n>> +\n>> +    data->dev_private = internals;\n>> +    data->port_id = eth_dev->data->port_id;\n>> +    data->nb_rx_queues = (uint16_t)nb_rx_queues;\n>> +    data->nb_tx_queues = (uint16_t)nb_tx_queues;\n>> +    data->dev_link = pmd_link;\n>> +    data->mac_addrs = &eth_addr;\n>> +\n>> +    eth_dev->data = data;\n>> +    eth_dev->dev_ops = &ops;\n>> +    eth_dev->pci_dev = pci_dev;\n>> +\n>> +    /* finally assign rx and tx ops */\n>> +    if (packet_copy) {\n>> +        eth_dev->rx_pkt_burst = eth_null_copy_rx;\n>> +        eth_dev->tx_pkt_burst = eth_null_copy_tx;\n>> +    } else {\n>> +        eth_dev->rx_pkt_burst = eth_null_rx;\n>> +        eth_dev->tx_pkt_burst = eth_null_tx;\n>> +    }\n>> +\n>> +    return 0;\n>> +\n>> +error:\n>> +    if (data)\n>> +        rte_free(data);\n>> +    if (pci_dev)\n>> +        rte_free(pci_dev);\n>> +    if (internals)\n>> +        rte_free(internals);\n>> +    return -1;\n>> +}\n>> +\n>> +static inline int\n>> +get_packet_size_arg(const char *key __rte_unused,\n>> +        const char *value, void *extra_args)\n>> +{\n>> +    const char *a = value;\n>> +    unsigned *packet_size = extra_args;\n>> +\n>> +    *packet_size = (unsigned)strtoul(a, NULL, 0);\n>> +    if (*packet_size == UINT_MAX)\n>> +        return -1;\n>> +\n>> +    return 0;\n>> +}\n>> +\n>> +static inline int\n>> +get_packet_copy_arg(const char *key __rte_unused,\n>> +        const char *value, void *extra_args)\n>> +{\n>> +    const char *a = value;\n>> +    unsigned *packet_copy = extra_args;\n>> +\n>> +    *packet_copy = (unsigned)strtoul(a, NULL, 0);\n>> +    if (*packet_copy == UINT_MAX)\n>> +        return -1;\n>> +\n>> +    return 0;\n>> +}\n>> +\n>> +static int\n>> +rte_pmd_null_devinit(const char *name, const char *params)\n>> +{\n>> +    unsigned numa_node;\n>> +    unsigned packet_size = default_packet_size;\n>> +    unsigned packet_copy = default_packet_copy;\n>> +    struct rte_kvargs *kvlist;\n>> +    int ret;\n>> +\n>> +    RTE_LOG(INFO, PMD, \"Initializing pmd_null for %s\\n\", name);\n>> +\n>> +    numa_node = rte_socket_id();\n>> +\n>> +    kvlist = rte_kvargs_parse(params, valid_arguments);\n>> +    if (kvlist == NULL)\n>> +        return -1;\n>> +\n>> +    if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) {\n>> +\n>> +        ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_SIZE_ARG,\n>> +                &get_packet_size_arg, &packet_size);\n>> +        if (ret < 0)\n>> +            return -1;\n>> +    }\n>> +\n>> +    if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) {\n>> +\n>> +        ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_COPY_ARG,\n>> +                &get_packet_copy_arg, &packet_copy);\n>> +        if (ret < 0)\n>> +            return -1;\n>> +    }\n>> +\n>> +    RTE_LOG(INFO, PMD, \"Configure pmd_null: packet size is %d, \"\n>> +            \"packet copy is %s\\n\", packet_size,\n>> +            packet_copy ? \"enabled\" : \"disabled\");\n>> +\n>> +    return eth_dev_null_create(name, numa_node, packet_size,\n>> packet_copy);\n>> +}\n>> +\n>> +static struct rte_driver pmd_null_drv = {\n>> +    .name = \"eth_null\",\n>> +    .type = PMD_VDEV,\n>> +    .init = rte_pmd_null_devinit,\n>> +};\n>> +\n>> +PMD_REGISTER_DRIVER(pmd_null_drv);\n>>\n>\n>",
        "headers": {
            "Return-Path": "<dev-bounces@dpdk.org>",
            "MIME-Version": "1.0",
            "X-Mailman-Version": "2.1.15",
            "From": "Tetsuya Mukawa <mukawa@igel.co.jp>",
            "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64;\n\trv:24.0) Gecko/20100101 Thunderbird/24.6.0",
            "List-Post": "<mailto:dev@dpdk.org>",
            "X-BeenThere": "dev@dpdk.org",
            "Content-Type": "text/plain; charset=ISO-8859-1",
            "References": "<mukawa@igel.co.jp>\n\t<1411129659-7132-1-git-send-email-mukawa@igel.co.jp>\n\t<1411129659-7132-2-git-send-email-mukawa@igel.co.jp>\n\t<541FD3BD.2060606@6wind.com>",
            "X-Original-To": "patchwork@dpdk.org",
            "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20130820;\n\th=x-gm-message-state:message-id:date:from:user-agent:mime-version:to\n\t:cc:subject:references:in-reply-to:content-type\n\t:content-transfer-encoding;\n\tbh=uk/lh54nqkmzW5PYYYs5SF/ZNtE/3rzsemjYD71u84g=;\n\tb=OYcY/9WCcP5P2rUNbDc2kYwcA3FiXBTOqeFZPaRzqoyUz/75IGnobMK28yCMaRtKyL\n\tnTRjaRzvkBGKwFknx1KFQGZPqe56qgtjMKMyh7FybT76PxnyT9hZmdYOEi57QCDc/FVp\n\t25dmHUG/EMWQWQYc7sngtmqWiirW/ZiNHkPwYe/S7/aozGJUJhSMN6fJKm/YONLTtgcN\n\t07IKzlsr55V6rFqDSKyWOQosglwIS5emCIezIdl2vNYO3oM52Ociw3J6j5rBQUMPRQq4\n\td/+dVEvzbwPDfglKgphN5MJovXI9qiKkVJmTzra5dUfQrYOv+Zk3lJGixRHWFP1rvFOg\n\tjokA==",
            "Received": [
                "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 97D432E81;\n\tMon, 22 Sep 2014 10:01:41 +0200 (CEST)",
                "from mail-pa0-f49.google.com (mail-pa0-f49.google.com\n\t[209.85.220.49]) by dpdk.org (Postfix) with ESMTP id C16FA231C\n\tfor <dev@dpdk.org>; Mon, 22 Sep 2014 10:01:39 +0200 (CEST)",
                "by mail-pa0-f49.google.com with SMTP id lf10so4027459pab.8\n\tfor <dev@dpdk.org>; Mon, 22 Sep 2014 01:07:41 -0700 (PDT)",
                "from [10.16.129.101] (napt.igel.co.jp. [219.106.231.132])\n\tby mx.google.com with ESMTPSA id\n\tca3sm8532259pbb.80.2014.09.22.01.07.39 for <multiple recipients>\n\t(version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128);\n\tMon, 22 Sep 2014 01:07:41 -0700 (PDT)"
            ],
            "Subject": "Re: [dpdk-dev] [RFC] librte_pmd_null: Add null PMD",
            "X-Received": "by 10.70.92.9 with SMTP id ci9mr26530740pdb.106.1411373261776;\n\tMon, 22 Sep 2014 01:07:41 -0700 (PDT)",
            "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
            "Message-ID": "<541FD8CA.7060500@igel.co.jp>",
            "Precedence": "list",
            "X-Gm-Message-State": "ALoCoQm63CRYyEyqLkL7GWO7Xm8BhevSFF58/pJLpOUd+ZPbWPQ0M7VGmmnd3/+ug1VR0DCayPFF",
            "Date": "Mon, 22 Sep 2014 17:07:38 +0900",
            "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
            "Sender": "\"dev\" <dev-bounces@dpdk.org>",
            "Errors-To": "dev-bounces@dpdk.org",
            "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
            "Cc": "nakajima.yoshihiro@lab.ntt.co.jp, masutani.hitoshi@lab.ntt.co.jp",
            "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
            "Delivered-To": "patchwork@dpdk.org",
            "In-Reply-To": "<541FD3BD.2060606@6wind.com>",
            "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
            "Content-Transfer-Encoding": "7bit",
            "To": "Ivan Boule <ivan.boule@6wind.com>, dev@dpdk.org"
        }
    }
]