get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 5873,
    "url": "http://patches.dpdk.org/api/patches/5873/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1435367948-20240-5-git-send-email-liang-min.wang@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1435367948-20240-5-git-send-email-liang-min.wang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1435367948-20240-5-git-send-email-liang-min.wang@intel.com",
    "date": "2015-06-27T01:19:07",
    "name": "[dpdk-dev,v9,4/5] examples: new example: l2fwd-ethtool",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "8abf72ed66d02a5882cd63f528ff2bd0db4a8f12",
    "submitter": {
        "id": 250,
        "url": "http://patches.dpdk.org/api/people/250/?format=api",
        "name": "Liang-Min Larry Wang",
        "email": "liang-min.wang@intel.com"
    },
    "delegate": null,
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1435367948-20240-5-git-send-email-liang-min.wang@intel.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/5873/comments/",
    "check": "pending",
    "checks": "http://patches.dpdk.org/api/patches/5873/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id E3B33CA58;\n\tSat, 27 Jun 2015 03:19:24 +0200 (CEST)",
            "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n\tby dpdk.org (Postfix) with ESMTP id 494C2CA28\n\tfor <dev@dpdk.org>; Sat, 27 Jun 2015 03:19:19 +0200 (CEST)",
            "from fmsmga001.fm.intel.com ([10.253.24.23])\n\tby fmsmga103.fm.intel.com with ESMTP; 26 Jun 2015 18:19:18 -0700",
            "from lwang14-mobl6.amr.corp.intel.com ([10.127.184.59])\n\tby fmsmga001.fm.intel.com with ESMTP; 26 Jun 2015 18:19:17 -0700"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.13,687,1427785200\"; d=\"scan'208\";a=\"735602652\"",
        "From": "Liang-Min Larry Wang <liang-min.wang@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Fri, 26 Jun 2015 21:19:07 -0400",
        "Message-Id": "<1435367948-20240-5-git-send-email-liang-min.wang@intel.com>",
        "X-Mailer": "git-send-email 2.1.4",
        "In-Reply-To": "<1435367948-20240-1-git-send-email-liang-min.wang@intel.com>",
        "References": "<1432946276-9424-1-git-send-email-liang-min.wang@intel.com>\n\t<1435367948-20240-1-git-send-email-liang-min.wang@intel.com>",
        "Cc": "Liang-Min Larry Wang <liang-min.wang@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v9 4/5] examples: new example: l2fwd-ethtool",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "The example includes an ethtool library and two applications:\none application is a non- DPDK process (nic-control)\nand the other is a DPDK l2fwd applicaiton (l2fwd-app).\nThe nic-control process sends ethtool alike device management\nrequests to l2fwd-app through a named pipe IPC. This example\nis designed to show how to build a ethtool shim library and\nhow to use ethtool apis to manage device parameters.\n\nSigned-off-by: Liang-Min Larry Wang <liang-min.wang@intel.com>\n---\n examples/l2fwd-ethtool/Makefile                  |   55 ++\n examples/l2fwd-ethtool/l2fwd-app/Makefile        |   58 ++\n examples/l2fwd-ethtool/l2fwd-app/main.c          | 1066 ++++++++++++++++++++++\n examples/l2fwd-ethtool/l2fwd-app/netdev_api.h    |  769 ++++++++++++++++\n examples/l2fwd-ethtool/l2fwd-app/shared_fifo.h   |  158 ++++\n examples/l2fwd-ethtool/lib/Makefile              |   55 ++\n examples/l2fwd-ethtool/lib/rte_ethtool.c         |  308 +++++++\n examples/l2fwd-ethtool/lib/rte_ethtool.h         |  384 ++++++++\n examples/l2fwd-ethtool/nic-control/Makefile      |   55 ++\n examples/l2fwd-ethtool/nic-control/nic_control.c |  471 ++++++++++\n 10 files changed, 3379 insertions(+)\n create mode 100644 examples/l2fwd-ethtool/Makefile\n create mode 100644 examples/l2fwd-ethtool/l2fwd-app/Makefile\n create mode 100644 examples/l2fwd-ethtool/l2fwd-app/main.c\n create mode 100644 examples/l2fwd-ethtool/l2fwd-app/netdev_api.h\n create mode 100644 examples/l2fwd-ethtool/l2fwd-app/shared_fifo.h\n create mode 100644 examples/l2fwd-ethtool/lib/Makefile\n create mode 100644 examples/l2fwd-ethtool/lib/rte_ethtool.c\n create mode 100644 examples/l2fwd-ethtool/lib/rte_ethtool.h\n create mode 100644 examples/l2fwd-ethtool/nic-control/Makefile\n create mode 100644 examples/l2fwd-ethtool/nic-control/nic_control.c",
    "diff": "diff --git a/examples/l2fwd-ethtool/Makefile b/examples/l2fwd-ethtool/Makefile\nnew file mode 100644\nindex 0000000..a753c33\n--- /dev/null\n+++ b/examples/l2fwd-ethtool/Makefile\n@@ -0,0 +1,55 @@\n+#   BSD LICENSE\n+#\n+#   Copyright(c) 2015 Intel Corporation. All rights reserved.\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+ifeq ($(RTE_SDK),)\n+$(error \"Please define RTE_SDK environment variable\")\n+endif\n+\n+# Default target, can be overriden by command line or environment\n+RTE_TARGET ?= x86_64-native-linuxapp-gcc\n+\n+include $(RTE_SDK)/mk/rte.vars.mk\n+unexport RTE_SRCDIR RTE_OUTPUT RTE_EXTMK\n+\n+ifneq ($(CONFIG_RTE_EXEC_ENV),\"linuxapp\")\n+$(error This application can only operate in a linuxapp environment, \\\n+please change the definition of the RTE_TARGET environment variable)\n+endif\n+\n+DIRS-y += lib nic-control l2fwd-app\n+\n+.PHONY: all clean $(DIRS-y)\n+\n+all: $(DIRS-y)\n+clean: $(DIRS-y)\n+\n+$(DIRS-y):\n+\t$(MAKE) -C $@ $(MAKECMDGOALS) O=$(RTE_OUTPUT)\ndiff --git a/examples/l2fwd-ethtool/l2fwd-app/Makefile b/examples/l2fwd-ethtool/l2fwd-app/Makefile\nnew file mode 100644\nindex 0000000..3d31cb1\n--- /dev/null\n+++ b/examples/l2fwd-ethtool/l2fwd-app/Makefile\n@@ -0,0 +1,58 @@\n+#   BSD LICENSE\n+#\n+#   Copyright(c) 2015 Intel Corporation. All rights reserved.\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+ifeq ($(RTE_SDK),)\n+$(error \"Please define RTE_SDK environment variable\")\n+endif\n+\n+# Default target, can be overriden by command line or environment\n+RTE_TARGET ?= x86_64-native-linuxapp-gcc\n+\n+include $(RTE_SDK)/mk/rte.vars.mk\n+\n+ifneq ($(CONFIG_RTE_EXEC_ENV),\"linuxapp\")\n+$(error This application can only operate in a linuxapp environment, \\\n+please change the definition of the RTE_TARGET environment variable)\n+endif\n+\n+# binary name\n+APP = l2fwd-app\n+\n+# all source are stored in SRCS-y\n+SRCS-y := main.c\n+\n+CFLAGS += -O3 -D_GNU_SOURCE -pthread -I$(SRCDIR)/../lib\n+CFLAGS += $(WERROR_FLAGS)\n+\n+LDLIBS += -lrte_ethtool\n+LDFLAGS += -L$(SRCDIR)/../lib/build\n+\n+include $(RTE_SDK)/mk/rte.extapp.mk\ndiff --git a/examples/l2fwd-ethtool/l2fwd-app/main.c b/examples/l2fwd-ethtool/l2fwd-app/main.c\nnew file mode 100644\nindex 0000000..19dd58c\n--- /dev/null\n+++ b/examples/l2fwd-ethtool/l2fwd-app/main.c\n@@ -0,0 +1,1066 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2015 Intel Corporation. All rights reserved.\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 <stdio.h>\n+#include <stdlib.h>\n+#include <string.h>\n+#include <stdint.h>\n+#include <inttypes.h>\n+#include <sys/types.h>\n+#include <sys/queue.h>\n+#include <netinet/in.h>\n+#include <setjmp.h>\n+#include <stdarg.h>\n+#include <ctype.h>\n+#include <errno.h>\n+#include <getopt.h>\n+#include <pthread.h>\n+#include <unistd.h>\n+\n+#include <rte_common.h>\n+#include <rte_log.h>\n+#include <rte_memory.h>\n+#include <rte_memcpy.h>\n+#include <rte_memzone.h>\n+#include <rte_tailq.h>\n+#include <rte_eal.h>\n+#include <rte_per_lcore.h>\n+#include <rte_launch.h>\n+#include <rte_atomic.h>\n+#include <rte_cycles.h>\n+#include <rte_prefetch.h>\n+#include <rte_lcore.h>\n+#include <rte_per_lcore.h>\n+#include <rte_branch_prediction.h>\n+#include <rte_interrupts.h>\n+#include <rte_pci.h>\n+#include <rte_random.h>\n+#include <rte_debug.h>\n+#include <rte_ether.h>\n+#include <rte_ethdev.h>\n+#include <rte_ring.h>\n+#include <rte_mempool.h>\n+#include <rte_mbuf.h>\n+#include \"rte_ethtool.h\"\n+#define NETDEV_OP_REPLY 1\n+#include \"netdev_api.h\"\n+\n+#define to_mac_type(x) (struct ether_addr *)(void *)(x)\n+#define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1\n+\n+#define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)\n+#define NB_MBUF   8192\n+\n+#define MAX_PKT_BURST 32\n+#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */\n+\n+#define is_vf_port(vf_mask, port_id) ((vf_mask & (1 << port_id)) > 0)\n+#define is_port_enabled(port_mask, port_id) ((port_mask & (1 << port_id)) > 0)\n+#define TX_PTHRESH 32\n+#define TX_HTHRESH 0\n+#define TX_WTHRESH 0\n+/*\n+ * Configurable number of RX/TX ring descriptors\n+ */\n+#define RTE_TEST_RX_DESC_DEFAULT 128\n+#define RTE_TEST_TX_DESC_DEFAULT 512\n+static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;\n+static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;\n+\n+/* ethernet addresses of ports */\n+static struct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS];\n+\n+/* mask of enabled ports */\n+static uint32_t l2fwd_enabled_port_mask;\n+\n+/* virtio setup enable */\n+static int virtio_setup;\n+\n+/* list of enabled ports */\n+static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS];\n+\n+static unsigned int l2fwd_rx_queue_per_lcore = 1;\n+\n+struct mbuf_table {\n+\tunsigned len;\n+\tstruct rte_mbuf *m_table[MAX_PKT_BURST];\n+};\n+\n+#define MAX_RX_QUEUE_PER_LCORE 16\n+#define MAX_TX_QUEUE_PER_PORT 16\n+struct lcore_queue_conf {\n+\tunsigned n_rx_port;\n+\tunsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE];\n+\tstruct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS];\n+\n+} __rte_cache_aligned;\n+struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];\n+\n+static struct rte_eth_conf port_conf = {\n+\t.rxmode = {\n+\t\t.split_hdr_size = 0,\n+\t\t.header_split   = 0, /**< Header Split disabled */\n+\t\t.hw_ip_checksum = 0, /**< IP checksum offload disabled */\n+\t\t.hw_vlan_filter = 0, /**< VLAN filtering disabled */\n+\t\t.jumbo_frame    = 0, /**< Jumbo Frame Support disabled */\n+\t\t.hw_strip_crc   = 0, /**< CRC stripped by hardware */\n+\t},\n+\t.txmode = {\n+\t\t.mq_mode = ETH_MQ_TX_NONE,\n+\t},\n+};\n+\n+static struct rte_eth_txconf tx_conf = {\n+\t.tx_thresh = {\n+\t\t.pthresh = TX_PTHRESH,\n+\t\t.hthresh = TX_HTHRESH,\n+\t\t.wthresh = TX_WTHRESH,\n+\t},\n+\t.tx_free_thresh = 32,\n+\t.tx_rs_thresh = 32,\n+\t.txq_flags = 0xf00,\n+};\n+\n+struct rte_mempool *l2fwd_pktmbuf_pool;\n+\n+/* Per-port statistics struct */\n+struct l2fwd_port_statistics {\n+\tuint64_t tx;\n+\tuint64_t rx;\n+\tuint64_t dropped;\n+} __rte_cache_aligned;\n+struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS];\n+\n+/* A tsc-based timer responsible for triggering statistics printout */\n+#define TIMER_MILLISECOND 2000000ULL /* around 1ms at 2 Ghz */\n+#define MAX_TIMER_PERIOD 86400 /* 1 day max */\n+/* default period is 10 seconds */\n+static int64_t timer_period = 10 * TIMER_MILLISECOND * 1000;\n+\n+/* IPC done checking utility function */\n+/* status of ipc completed */\n+static rte_atomic64_t ipc_done;\n+\n+static inline void init_ipc_done(void)\n+{\n+\trte_atomic64_init(&ipc_done);\n+}\n+\n+static inline int is_ipc_done(void)\n+{\n+\treturn rte_atomic64_read(&ipc_done) > 0;\n+}\n+\n+static inline void set_ipc_done(void)\n+{\n+\trte_atomic64_inc(&ipc_done);\n+}\n+\n+/* Print out statistics on packets dropped */\n+static void\n+print_stats(void)\n+{\n+\tuint64_t total_packets_dropped, total_packets_tx, total_packets_rx;\n+\tunsigned portid;\n+\n+\ttotal_packets_dropped = 0;\n+\ttotal_packets_tx = 0;\n+\ttotal_packets_rx = 0;\n+\n+\tconst char clr[] = { 27, '[', '2', 'J', '\\0' };\n+\tconst char topLeft[] = { 27, '[', '1', ';', '1', 'H', '\\0' };\n+\n+\t\t/* Clear screen and move to top left */\n+\tprintf(\"%s%s\", clr, topLeft);\n+\n+\tprintf(\"\\nPort statistics ====================================\");\n+\n+\tfor (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {\n+\t\t/* skip disabled ports */\n+\t\tif ((l2fwd_enabled_port_mask & (1 << portid)) == 0)\n+\t\t\tcontinue;\n+\t\tprintf(\"\\nStatistics for port %u ----------------------------\",\n+\t\t\tportid);\n+\t\tprintf(\"\\nPackets sent: %24\"PRIu64, port_statistics[portid].tx);\n+\t\tprintf(\"\\nPackets received: %20\"PRIu64,\n+\t\t\tport_statistics[portid].rx);\n+\t\tprintf(\"\\nPackets dropped: %21\"PRIu64,\n+\t\t\tport_statistics[portid].dropped);\n+\n+\t\ttotal_packets_dropped += port_statistics[portid].dropped;\n+\t\ttotal_packets_tx += port_statistics[portid].tx;\n+\t\ttotal_packets_rx += port_statistics[portid].rx;\n+\t}\n+\tprintf(\"\\nAggregate statistics ===============================\");\n+\tprintf(\"\\nTotal packets sent: %18\"PRIu64, total_packets_tx);\n+\tprintf(\"\\nTotal packets received: %14\"PRIu64, total_packets_rx);\n+\tprintf(\"\\nTotal packets dropped: %15\"PRIu64, total_packets_dropped);\n+\tprintf(\"\\n====================================================\\n\");\n+}\n+\n+/* Send the burst of packets on an output interface */\n+static int\n+l2fwd_send_burst(struct lcore_queue_conf *qconf, unsigned n, uint8_t port)\n+{\n+\tstruct rte_mbuf **m_table;\n+\tunsigned ret;\n+\tunsigned queueid = 0;\n+\n+\tm_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table;\n+\n+\tret = rte_eth_tx_burst(port, (uint16_t) queueid, m_table, (uint16_t) n);\n+\tport_statistics[port].tx += ret;\n+\tif (unlikely(ret < n)) {\n+\t\tport_statistics[port].dropped += (n - ret);\n+\t\tdo {\n+\t\t\trte_pktmbuf_free(m_table[ret]);\n+\t\t} while (++ret < n);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/* Enqueue packets for TX and prepare them to be sent */\n+static int\n+l2fwd_send_packet(struct rte_mbuf *m, uint8_t port)\n+{\n+\tunsigned lcore_id, len;\n+\tstruct lcore_queue_conf *qconf;\n+\n+\tlcore_id = rte_lcore_id();\n+\n+\tqconf = &lcore_queue_conf[lcore_id];\n+\tlen = qconf->tx_mbufs[port].len;\n+\tqconf->tx_mbufs[port].m_table[len] = m;\n+\tlen++;\n+\n+\t/* enough pkts to be sent */\n+\tif (unlikely(len == MAX_PKT_BURST)) {\n+\t\tl2fwd_send_burst(qconf, MAX_PKT_BURST, port);\n+\t\tlen = 0;\n+\t}\n+\n+\tqconf->tx_mbufs[port].len = len;\n+\treturn 0;\n+}\n+\n+static void\n+l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)\n+{\n+\tstruct ether_hdr *eth;\n+\tvoid *tmp;\n+\tunsigned dst_port;\n+\n+\tdst_port = l2fwd_dst_ports[portid];\n+\teth = rte_pktmbuf_mtod(m, struct ether_hdr *);\n+\n+\t/* 02:00:00:00:00:xx */\n+\ttmp = &eth->d_addr.addr_bytes[0];\n+\t*((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dst_port << 40);\n+\n+\t/* src addr */\n+\tether_addr_copy(&l2fwd_ports_eth_addr[dst_port], &eth->s_addr);\n+\n+\tl2fwd_send_packet(m, (uint8_t) dst_port);\n+}\n+\n+/* main processing loop */\n+static void\n+l2fwd_main_loop(void)\n+{\n+\tstruct rte_mbuf *pkts_burst[MAX_PKT_BURST];\n+\tstruct rte_mbuf *m;\n+\tunsigned lcore_id;\n+\tuint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc;\n+\tunsigned i, j, portid, nb_rx;\n+\tstruct lcore_queue_conf *qconf;\n+\tconst uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) /\n+\t\t\t\t\tUS_PER_S * BURST_TX_DRAIN_US;\n+\n+\tprev_tsc = 0;\n+\ttimer_tsc = 0;\n+\n+\tlcore_id = rte_lcore_id();\n+\tqconf = &lcore_queue_conf[lcore_id];\n+\n+\tif (qconf->n_rx_port == 0) {\n+\t\tRTE_LOG(INFO, L2FWD, \"lcore %u has nothing to do\\n\", lcore_id);\n+\t\treturn;\n+\t}\n+\n+\tRTE_LOG(INFO, L2FWD, \"entering main loop on lcore %u\\n\", lcore_id);\n+\n+\tfor (i = 0; i < qconf->n_rx_port; i++) {\n+\n+\t\tportid = qconf->rx_port_list[i];\n+\t\tRTE_LOG(INFO, L2FWD, \" -- lcoreid=%u portid=%u\\n\", lcore_id,\n+\t\t\tportid);\n+\t}\n+\n+\tif (virtio_setup) {\n+\t\twhile (is_ipc_done() == 0)\n+\t\t\tusleep(50);\n+\t}\n+\n+\twhile (1) {\n+\t\tcur_tsc = rte_rdtsc();\n+\n+\t\t/* TX burst queue drain */\n+\t\tdiff_tsc = cur_tsc - prev_tsc;\n+\t\tif (unlikely(diff_tsc > drain_tsc)) {\n+\n+\t\t\tfor (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {\n+\t\t\t\tif (qconf->tx_mbufs[portid].len == 0)\n+\t\t\t\t\tcontinue;\n+\t\t\t\tl2fwd_send_burst(&lcore_queue_conf[lcore_id],\n+\t\t\t\t\t\t qconf->tx_mbufs[portid].len,\n+\t\t\t\t\t\t (uint8_t) portid);\n+\t\t\t\tqconf->tx_mbufs[portid].len = 0;\n+\t\t\t}\n+\n+\t\t\t/* if timer is enabled */\n+\t\t\tif (timer_period > 0) {\n+\n+\t\t\t\t/* advance the timer */\n+\t\t\t\ttimer_tsc += diff_tsc;\n+\n+\t\t\t\t/* if timer has reached its timeout */\n+\t\t\t\tif (unlikely(timer_tsc >=\n+\t\t\t\t    (uint64_t) timer_period)) {\n+\n+\t\t\t\t\t/* do this only on master core */\n+\t\t\t\t\tif (lcore_id ==\n+\t\t\t\t\t    rte_get_master_lcore()) {\n+\t\t\t\t\t\tprint_stats();\n+\t\t\t\t\t\t/* reset the timer */\n+\t\t\t\t\t\ttimer_tsc = 0;\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t}\n+\n+\t\t\tprev_tsc = cur_tsc;\n+\t\t}\n+\n+\t\t/*\n+\t\t * Read packet from RX queues\n+\t\t */\n+\t\tfor (i = 0; i < qconf->n_rx_port; i++) {\n+\n+\t\t\tportid = qconf->rx_port_list[i];\n+\t\t\tnb_rx = rte_eth_rx_burst((uint8_t) portid, 0,\n+\t\t\t\t\t\t pkts_burst, MAX_PKT_BURST);\n+\n+\t\t\tport_statistics[portid].rx += nb_rx;\n+\n+\t\t\tfor (j = 0; j < nb_rx; j++) {\n+\t\t\t\tm = pkts_burst[j];\n+\t\t\t\trte_prefetch0(rte_pktmbuf_mtod(m, void *));\n+\t\t\t\tl2fwd_simple_forward(m, portid);\n+\t\t\t}\n+\t\t}\n+\t}\n+}\n+\n+static int\n+l2fwd_launch_one_lcore(__attribute__((unused)) void *dummy)\n+{\n+\tl2fwd_main_loop();\n+\treturn 0;\n+}\n+\n+/* display usage */\n+static void\n+l2fwd_usage(const char *prgname)\n+{\n+\tprintf(\"%s [EAL options] -- -p PORTMASK [-q NQ]\\n\"\n+\t\t\"  -p PORTMASK: hexadecimal bitmask of ports to configure\\n\"\n+\t\t\"  -q NQ: number of queue (=ports) per lcore (default is 1)\\n\"\n+\t\t\"  -V : setting rx/tx mode to enable virtio\\n\"\n+\t\t\"  -T PERIOD: statistics will be refreshed each PERIOD seconds\",\n+\t\tprgname);\n+\tprintf(\"(0 to disable, 10 default, 86400 maximum)\\n\");\n+}\n+\n+static int\n+l2fwd_parse_portmask(const char *portmask)\n+{\n+\tchar *end = NULL;\n+\tunsigned long pm;\n+\n+\t/* parse hexadecimal string */\n+\tpm = strtoul(portmask, &end, 16);\n+\tif ((portmask[0] == '\\0') || (end == NULL) || (*end != '\\0'))\n+\t\treturn -1;\n+\n+\tif (pm == 0)\n+\t\treturn -1;\n+\n+\treturn pm;\n+}\n+\n+static unsigned int\n+l2fwd_parse_nqueue(const char *q_arg)\n+{\n+\tchar *end = NULL;\n+\tunsigned long n;\n+\n+\t/* parse hexadecimal string */\n+\tn = strtoul(q_arg, &end, 10);\n+\tif ((q_arg[0] == '\\0') || (end == NULL) || (*end != '\\0'))\n+\t\treturn 0;\n+\tif (n == 0)\n+\t\treturn 0;\n+\tif (n >= MAX_RX_QUEUE_PER_LCORE)\n+\t\treturn 0;\n+\n+\treturn n;\n+}\n+\n+static int\n+l2fwd_parse_timer_period(const char *q_arg)\n+{\n+\tchar *end = NULL;\n+\tint n;\n+\n+\t/* parse number string */\n+\tn = strtol(q_arg, &end, 10);\n+\tif ((q_arg[0] == '\\0') || (end == NULL) || (*end != '\\0'))\n+\t\treturn -1;\n+\tif (n >= MAX_TIMER_PERIOD)\n+\t\treturn -1;\n+\n+\treturn n;\n+}\n+\n+static int\n+l2fwd_parse_virtio_setup(const char *q_arg)\n+{\n+\tchar *end = NULL;\n+\tint n;\n+\n+\t/* parse number string */\n+\tn = strtol(q_arg, &end, 10);\n+\tif ((q_arg[0] == '\\0') || (end == NULL) || (*end != '\\0'))\n+\t\treturn -1;\n+\tif (n >= MAX_TIMER_PERIOD)\n+\t\treturn -1;\n+\n+\treturn n;\n+}\n+\n+/* Parse the argument given in the command line of the application */\n+static int\n+l2fwd_parse_args(int argc, char **argv)\n+{\n+\tint opt, ret;\n+\tchar **argvopt;\n+\tint option_index;\n+\tchar *prgname = argv[0];\n+\tstatic struct option lgopts[] = {\n+\t\t{NULL, 0, 0, 0}\n+\t};\n+\n+\targvopt = argv;\n+\n+\twhile ((opt = getopt_long(argc, argvopt, \"p:q:T:V:\",\n+\t\t\t\t  lgopts, &option_index)) != EOF) {\n+\n+\t\tswitch (opt) {\n+\t\t/* portmask */\n+\t\tcase 'p':\n+\t\t\tl2fwd_enabled_port_mask = l2fwd_parse_portmask(optarg);\n+\t\t\tif (l2fwd_enabled_port_mask == 0) {\n+\t\t\t\tprintf(\"invalid portmask\\n\");\n+\t\t\t\tl2fwd_usage(prgname);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tbreak;\n+\n+\t\t/* nqueue */\n+\t\tcase 'q':\n+\t\t\tl2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg);\n+\t\t\tif (l2fwd_rx_queue_per_lcore == 0) {\n+\t\t\t\tprintf(\"invalid queue number\\n\");\n+\t\t\t\tl2fwd_usage(prgname);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tbreak;\n+\n+\t\t/* timer period */\n+\t\tcase 'T':\n+\t\t\ttimer_period = l2fwd_parse_timer_period(optarg) *\n+\t\t\t\t1000 * TIMER_MILLISECOND;\n+\t\t\tif (timer_period < 0) {\n+\t\t\t\tprintf(\"invalid timer period\\n\");\n+\t\t\t\tl2fwd_usage(prgname);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tbreak;\n+\n+\t\t/* virtio setup */\n+\t\tcase 'V':\n+\t\t\t/* get option as the pf mac addr */\n+\t\t\tvirtio_setup = l2fwd_parse_virtio_setup(optarg);\n+\t\t\tif (virtio_setup) {\n+\t\t\t\tport_conf.rxmode.hw_vlan_strip = 0;\n+\t\t\t\tport_conf.rxmode.hw_vlan_extend = 0;\n+\t\t\t}\n+\t\t\tbreak;\n+\n+\t\t/* long options */\n+\t\tcase 0:\n+\t\t\tl2fwd_usage(prgname);\n+\t\t\treturn -1;\n+\n+\t\tdefault:\n+\t\t\tl2fwd_usage(prgname);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\tif (optind >= 0)\n+\t\targv[optind-1] = prgname;\n+\n+\tret = optind-1;\n+\toptind = 0; /* reset getopt lib */\n+\treturn ret;\n+}\n+\n+/* Check the link status of all ports in up to 9s, and print them finally */\n+static void\n+check_all_ports_link_status(uint8_t port_num, uint32_t port_mask)\n+{\n+#define CHECK_INTERVAL 100 /* 100ms */\n+#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */\n+\tuint8_t portid, count, all_ports_up, print_flag = 0;\n+\tstruct rte_eth_link link;\n+\n+\tprintf(\"\\nChecking link status!!!\");\n+\tfflush(stdout);\n+\tfor (count = 0; count <= MAX_CHECK_TIME; count++) {\n+\t\tall_ports_up = 1;\n+\t\tfor (portid = 0; portid < port_num; portid++) {\n+\t\t\tif ((port_mask & (1 << portid)) == 0)\n+\t\t\t\tcontinue;\n+\t\t\tmemset(&link, 0, sizeof(link));\n+\t\t\trte_eth_link_get_nowait(portid, &link);\n+\t\t\t/* print link status if flag set */\n+\t\t\tif (print_flag == 1) {\n+\t\t\t\tif (link.link_status) {\n+\t\t\t\t\tprintf(\"Port %d Link Up - speed %u \"\n+\t\t\t\t\t\t, (uint8_t)portid,\n+\t\t\t\t\t\t(unsigned)link.link_speed);\n+\t\t\t\t\tprintf(\"Mbps - %s\\n\", (link.link_duplex\n+\t\t\t\t\t\t== ETH_LINK_FULL_DUPLEX) ?\n+\t\t\t\t\t\t(\"full-duplex\") :\n+\t\t\t\t\t\t(\"half-duplex\\n\"));\n+\t\t\t\t} else\n+\t\t\t\t\tprintf(\"Port %d Link Down\\n\",\n+\t\t\t\t\t\t(uint8_t)portid);\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\t/* clear all_ports_up flag if any link down */\n+\t\t\tif (link.link_status == 0) {\n+\t\t\t\tall_ports_up = 0;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\t/* after finally printing all link status, get out */\n+\t\tif (print_flag == 1)\n+\t\t\tbreak;\n+\n+\t\tif (all_ports_up == 0) {\n+\t\t\tprintf(\".\");\n+\t\t\tfflush(stdout);\n+\t\t\trte_delay_ms(CHECK_INTERVAL);\n+\t\t}\n+\n+\t\t/* set the print_flag if all ports up or timeout */\n+\t\tif (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {\n+\t\t\tprint_flag = 1;\n+\t\t\tprintf(\"done\\n\");\n+\t\t}\n+\t}\n+}\n+\n+static inline char*\n+mac_addr_str(unsigned char *mac_addr)\n+{\n+#define MAC_STR_SIZE (3*MAC_ADDR_SIZE+1)\n+\tstatic char addr_string[MAC_STR_SIZE];\n+\n+\tsnprintf(addr_string, MAC_STR_SIZE, \"%02x:%02x:%02x:%02x:%02x:%02x\",\n+\t\tmac_addr[0], mac_addr[1], mac_addr[2],\n+\t\tmac_addr[3], mac_addr[4], mac_addr[5]);\n+\treturn addr_string;\n+}\n+\n+static int\n+proc_ipc_begin(struct nic_info *info, uint16_t req_id, void *mac_ptr)\n+{\n+\tstruct ethtool_drvinfo drvinfo;\n+\tuint8_t mac_addr[MAC_ADDR_SIZE];\n+\tuint8_t param[4], port_id, num_of_ports = info->num_of_ports;\n+\tuint32_t param2[2];\n+\tuint8_t *new_mac_addr = mac_ptr;\n+\tint status;\n+\n+\tparam[0] = num_of_ports;\n+\tinfo->vf_port_mask = 0;\n+\tfor (port_id = 0; port_id < num_of_ports; port_id++) {\n+\t\tstatus = rte_ethtool_get_drvinfo(port_id, &drvinfo);\n+\t\tif (status) {\n+\t\t\tprintf(\"get_drvinfo from port #%d fails\\n\", port_id);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tinfo->vf_port_mask |= (drvinfo.eedump_len == 0?1:0) << port_id;\n+\t\trte_ethtool_net_stop(port_id);\n+\t}\n+\tparam2[0] = info->port_mask;\n+\tparam2[1] = info->vf_port_mask;\n+\n+\tfor (port_id = 0; port_id < num_of_ports; port_id++) {\n+\t\trte_ethtool_net_open(port_id);\n+\t\t/* Using rte_ethtool_net_set_rx_mode instead of */\n+\t\t/* rte_eth_promiscuous_enable to test */\n+\t\t/* rte_ethtool_net_set_rx_mode */\n+\t\tif (!is_vf_port(info->vf_port_mask, port_id)) {\n+\t\t\tstruct rte_eth_dev *dev = &rte_eth_devices[port_id];\n+\t\t\tstruct rte_eth_dev_data *dev_data =\n+\t\t\t\t(struct rte_eth_dev_data *)dev->data;\n+\n+\t\t\tdev_data->promiscuous = 1;\n+\n+\t\t\trte_ethtool_net_set_rx_mode(port_id);\n+\t\t}\n+\t\trte_ethtool_net_get_mac_addr(port_id, (void *)mac_addr);\n+\t\tprintf(\"Port #%d init mac address is\", port_id);\n+\t\tprintf(\" %s\", mac_addr_str(mac_addr));\n+\n+\t\tif (is_vf_port(info->vf_port_mask, port_id)) {\n+\t\t\t/* use new mac addr if the default addr is not valid */\n+\t\t\tif (!is_valid_assigned_ether_addr(to_mac_type(mac_addr))\n+\t\t\t\t) {\n+\t\t\t\tif (rte_ethtool_net_set_mac_addr(port_id,\n+\t\t\t\t\t(void *)new_mac_addr) == 0) {\n+\t\t\t\t\tprintf(\", and re-assigned to \");\n+\t\t\t\t\tprintf(\"%s\\n\",\n+\t\t\t\t\tmac_addr_str(new_mac_addr));\n+\t\t\t\t\tnew_mac_addr[MAC_ADDR_SIZE-1]++;\n+\t\t\t\t} else {\n+\t\t\t\t\tprintf(\"\\n\");\n+\t\t\t\t}\n+\t\t\t}\n+\t\t} else {\n+\t\t\tprintf(\"\\n\");\n+\t\t}\n+\t}\n+\n+\tsend_reply2(req_id, 1, param, (uint16_t)(sizeof(uint32_t)*2), param2);\n+\treturn 0;\n+}\n+\n+static inline void\n+proc_no_action(uint16_t req_id)\n+{\n+\tsend_reply(req_id, 0, NULL);\n+}\n+\n+static inline void\n+proc_invalid(uint16_t req_id)\n+{\n+\tsend_reply(req_id, BAD_RETURN(0), NULL);\n+}\n+\n+static void*\n+ethtool(void *ctx)\n+{\n+\tstruct nic_info *info = ctx;\n+\tint keep_req = 1;\n+\tint reg_count, eeprom_size;\n+\tuint16_t req_id, param1_size, param2_size;\n+\tuint8_t req_type, port_id;\n+\tint status;\n+\tuint8_t param1[MAXI_PARA];\n+\tuint8_t param2[MAXI_PARA];\n+\tuint8_t reply1[MAXI_DATA];\n+\tvoid *first_param\t= FIRST_PARAM(param1);\n+\n+\tinit_rep_pipe();\n+\twhile (1) {\n+\t\tread_request(&req_id, &req_type, &param1_size, param1,\n+\t\t\t&param2_size, param2);\n+\t\tif (req_type != (enum req_t)ipc_begin)\n+\t\t\tproc_invalid(req_id);\n+\t\telse\n+\t\t\tbreak;\n+\t}\n+\tproc_ipc_begin(info, req_id, first_param);\n+\n+\tset_ipc_done();\n+\treg_count = eeprom_size = 0;\n+\n+\twhile (keep_req) {\n+\t\tstatus = NETDEV_INVALID;\n+\t\tread_request(&req_id, &req_type, &param1_size, param1,\n+\t\t\t&param2_size, param2);\n+\t\tport_id = param1[0];\n+\n+\t\tswitch ((enum req_t)req_type) {\n+\t\tcase get_drvinfo:\n+\t\t\tstatus = proc_ethtool_get_drvinfo(port_id, req_id,\n+\t\t\t\tfirst_param);\n+\t\t\tbreak;\n+\n+\t\tcase get_regs_len:\n+\t\t\tstatus = reg_count = proc_ethtool_get_regs_len(\n+\t\t\t\tport_id, req_id);\n+\t\t\tbreak;\n+\n+\t\tcase get_regs:\n+\t\t\tif (reg_count == 0)\n+\t\t\t\treg_count = rte_ethtool_get_regs_len(port_id);\n+\t\t\tif (reg_count)\n+\t\t\t\tstatus = proc_ethtool_get_regs(port_id, req_id,\n+\t\t\t\tfirst_param, reply1);\n+\t\t\tbreak;\n+\n+\t\tcase get_link:\n+\t\t\tstatus = proc_ethtool_get_link(port_id, req_id);\n+\t\t\tbreak;\n+\n+\t\tcase get_eeprom_len:\n+\t\t\tif (eeprom_size == 0)\n+\t\t\t\teeprom_size = rte_ethtool_get_eeprom_len(\n+\t\t\t\tport_id);\n+\t\t\tstatus = proc_ethtool_get_eeprom_len(port_id, req_id);\n+\t\t\tbreak;\n+\n+\t\tcase get_eeprom:\n+\t\t\tstatus = proc_ethtool_get_eeprom(port_id, req_id,\n+\t\t\t\tfirst_param, reply1);\n+\t\t\tbreak;\n+\n+\t\tcase set_eeprom:\n+\t\t\tstatus = proc_ethtool_set_eeprom(port_id, req_id,\n+\t\t\t\tfirst_param, param2);\n+\t\t\tbreak;\n+\n+\t\tcase get_pauseparam:\n+\t\t\t{\n+\t\t\t\tstruct ethtool_pauseparam *pause_param =\n+\t\t\t\t\t(void *)reply1;\n+\n+\t\t\t\tstatus = proc_ethtool_get_pauseparam(port_id,\n+\t\t\t\t\treq_id, pause_param);\n+\n+\t\t\t\tif (status != 0) {\n+\t\t\t\t\tprintf(\"get_pauseparam return\");\n+\t\t\t\t\tprintf(\" status %d\\n\", status);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tbreak;\n+\n+\t\tcase set_pauseparam:\n+\t\t\t{\n+\t\t\t\tstruct ethtool_pauseparam *pause_param =\n+\t\t\t\t\t(void *)reply1;\n+\n+\t\t\t\tstatus = proc_ethtool_set_pauseparam(port_id,\n+\t\t\t\t\treq_id, pause_param);\n+\n+\t\t\t\tif (status != 0) {\n+\t\t\t\t\tprintf(\"set_pauseparam return\");\n+\t\t\t\t\tprintf(\" status %d\\n\", status);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tbreak;\n+\n+\t\tcase dev_open:\n+\t\t\tstatus = proc_net_open(port_id, req_id);\n+\t\t\tbreak;\n+\n+\t\tcase dev_stop:\n+\t\t\tstatus = proc_net_stop(port_id, req_id);\n+\t\t\tbreak;\n+\n+\t\tcase set_rx_mode:\n+\t\t\tstatus = proc_net_set_rx_mode(port_id, req_id);\n+\t\t\tbreak;\n+\n+\t\tcase get_mac_addr:\n+\t\t\tstatus = proc_net_get_mac_addr(port_id,\n+\t\t\t\treq_id, first_param);\n+\t\t\tbreak;\n+\n+\t\tcase set_mac_addr:\n+\t\t\tstatus = proc_net_set_mac_addr(port_id,\n+\t\t\t\treq_id, first_param);\n+\t\t\tbreak;\n+\n+\t\tcase validate_addr:\n+\t\t\tstatus = proc_net_validate_addr(port_id,\n+\t\t\t\treq_id, first_param);\n+\t\t\tbreak;\n+\n+\t\tcase set_config:\n+\t\t\tstatus = proc_net_set_config(port_id,\n+\t\t\t\treq_id, first_param);\n+\t\t\tbreak;\n+\n+\t\tcase change_mtu:\n+\t\t\tstatus = proc_net_change_mtu(port_id,\n+\t\t\t\treq_id, first_param);\n+\t\t\tbreak;\n+\n+\t\tcase get_stats64:\n+\t\t\tstatus = proc_net_get_stats64(port_id,\n+\t\t\t\treq_id, reply1);\n+\t\t\tbreak;\n+\n+\t\tcase vlan_rx_add_vid:\n+\t\t\tstatus = proc_net_vlan_rx_add_vid(port_id,\n+\t\t\t\treq_id, first_param);\n+\t\t\tbreak;\n+\n+\t\tcase vlan_rx_kill_vid:\n+\t\t\tstatus = proc_net_vlan_rx_kill_vid(port_id,\n+\t\t\t\treq_id, first_param);\n+\t\t\tbreak;\n+\n+\t\tcase ipc_end:\n+\t\t\tkeep_req = 0;\n+\t\t\tproc_no_action(req_id);\n+\t\t\tstatus = 0;\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\tproc_invalid(req_id);\n+\t\t\tprintf(\"unsupported service request type:\");\n+\t\t\tprintf(\" %d\\n\", req_type);\n+\t\t\tbreak;\n+\t\t}\n+\t\tif (status < 0)\n+\t\t\tprintf(\"Request type (=%d) failed\\n\", (int)req_type);\n+\t\t/* check if termination flag is set */\n+\t}\n+\tprintf(\"IPC session is over\\n\");\n+\treturn NULL;\n+}\n+\n+int\n+main(int argc, char **argv)\n+{\n+\tstruct lcore_queue_conf *qconf;\n+\tstruct rte_eth_dev_info dev_info;\n+\tint ret;\n+\tuint8_t nb_ports;\n+\tuint8_t nb_ports_available;\n+\tuint8_t portid, last_port;\n+\tunsigned lcore_id, rx_lcore_id;\n+\tunsigned nb_ports_in_mask = 0;\n+\n+\tinit_ipc_done();\n+\t/* init EAL */\n+\tret = rte_eal_init(argc, argv);\n+\tif (ret < 0)\n+\t\trte_exit(EXIT_FAILURE, \"Invalid EAL arguments\\n\");\n+\targc -= ret;\n+\targv += ret;\n+\n+\t/* parse application arguments (after the EAL ones) */\n+\tret = l2fwd_parse_args(argc, argv);\n+\tif (ret < 0)\n+\t\trte_exit(EXIT_FAILURE, \"Invalid L2FWD arguments\\n\");\n+\n+\t/* create the mbuf pool */\n+\tl2fwd_pktmbuf_pool =\n+\t\trte_mempool_create(\"mbuf_pool\", NB_MBUF,\n+\t\t\t\t   MBUF_SIZE, 32,\n+\t\t\t\t   sizeof(struct rte_pktmbuf_pool_private),\n+\t\t\t\t   rte_pktmbuf_pool_init, NULL,\n+\t\t\t\t   rte_pktmbuf_init, NULL,\n+\t\t\t\t   rte_socket_id(), 0);\n+\tif (l2fwd_pktmbuf_pool == NULL)\n+\t\trte_exit(EXIT_FAILURE, \"Cannot init mbuf pool\\n\");\n+\n+\tnb_ports = rte_eth_dev_count();\n+\tif (nb_ports == 0)\n+\t\trte_exit(EXIT_FAILURE, \"No Ethernet ports - bye\\n\");\n+\n+\tif (nb_ports > RTE_MAX_ETHPORTS)\n+\t\tnb_ports = RTE_MAX_ETHPORTS;\n+\n+\t/* reset l2fwd_dst_ports */\n+\tfor (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)\n+\t\tl2fwd_dst_ports[portid] = 0;\n+\tlast_port = 0;\n+\n+\t/*\n+\t * Each logical core is assigned a dedicated TX queue on each port.\n+\t */\n+\tfor (portid = 0; portid < nb_ports; portid++) {\n+\t\t/* skip ports that are not enabled */\n+\t\tif ((l2fwd_enabled_port_mask & (1 << portid)) == 0)\n+\t\t\tcontinue;\n+\n+\t\tif (nb_ports_in_mask % 2) {\n+\t\t\tl2fwd_dst_ports[portid] = last_port;\n+\t\t\tl2fwd_dst_ports[last_port] = portid;\n+\t\t} else\n+\t\t\tlast_port = portid;\n+\n+\t\tnb_ports_in_mask++;\n+\n+\t\trte_eth_dev_info_get(portid, &dev_info);\n+\t}\n+\tif (nb_ports_in_mask % 2) {\n+\t\tprintf(\"Notice: odd number of ports in portmask.\\n\");\n+\t\tl2fwd_dst_ports[last_port] = last_port;\n+\t}\n+\n+\trx_lcore_id = 0;\n+\tqconf = NULL;\n+\n+\t/* Initialize the port/queue configuration of each logical core */\n+\tfor (portid = 0; portid < nb_ports; portid++) {\n+\t\t/* skip ports that are not enabled */\n+\t\tif ((l2fwd_enabled_port_mask & (1 << portid)) == 0)\n+\t\t\tcontinue;\n+\n+\t\t/* get the lcore_id for this port */\n+\t\twhile (rte_lcore_is_enabled(rx_lcore_id) == 0 ||\n+\t\t\tlcore_queue_conf[rx_lcore_id].n_rx_port ==\n+\t\t\tl2fwd_rx_queue_per_lcore) {\n+\t\t\trx_lcore_id++;\n+\t\t\tif (rx_lcore_id >= RTE_MAX_LCORE)\n+\t\t\t\trte_exit(EXIT_FAILURE, \"Not enough cores\\n\");\n+\t\t}\n+\n+\t\tif (qconf != &lcore_queue_conf[rx_lcore_id])\n+\t\t\t/* Assigned a new logical core in the loop above. */\n+\t\t\tqconf = &lcore_queue_conf[rx_lcore_id];\n+\n+\t\tqconf->rx_port_list[qconf->n_rx_port] = portid;\n+\t\tqconf->n_rx_port++;\n+\t\tprintf(\"Lcore %u: RX port %u\\n\", rx_lcore_id,\n+\t\t\t(unsigned) portid);\n+\t}\n+\n+\tnb_ports_available = nb_ports;\n+\n+\t/* Initialise each port */\n+\tfor (portid = 0; portid < nb_ports; portid++) {\n+\t\t/* skip ports that are not enabled */\n+\t\tif ((l2fwd_enabled_port_mask & (1 << portid)) == 0) {\n+\t\t\tprintf(\"Skipping disabled port %u\\n\",\n+\t\t\t\t(unsigned) portid);\n+\t\t\tnb_ports_available--;\n+\t\t\tcontinue;\n+\t\t}\n+\t\t/* init port */\n+\t\tprintf(\"Initializing port %u... \", (unsigned) portid);\n+\t\tfflush(stdout);\n+\t\tret = rte_eth_dev_configure(portid, 1, 1, &port_conf);\n+\t\tif (ret < 0)\n+\t\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\"Cannot configure device: err=%d, port=%u\\n\",\n+\t\t\t\tret, (unsigned) portid);\n+\n+\t\trte_eth_macaddr_get(portid, &l2fwd_ports_eth_addr[portid]);\n+\n+\t\t/* init one RX queue */\n+\t\tfflush(stdout);\n+\t\tret = rte_eth_rx_queue_setup(portid, 0, nb_rxd,\n+\t\t\t\t\trte_eth_dev_socket_id(portid),\n+\t\t\t\t\tNULL,\n+\t\t\t\t\tl2fwd_pktmbuf_pool);\n+\t\tif (ret < 0)\n+\t\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\"rte_eth_rx_queue_setup:err=%d, port=%u\\n\",\n+\t\t\t\t  ret, (unsigned) portid);\n+\n+\t\t/* init one TX queue on each port */\n+\t\tfflush(stdout);\n+\t\tif (virtio_setup) {\n+\t\t\tret = rte_eth_tx_queue_setup(portid, 0, nb_txd,\n+\t\t\t\trte_eth_dev_socket_id(portid), &tx_conf);\n+\t\t} else {\n+\t\t\tret = rte_eth_tx_queue_setup(portid, 0, nb_txd,\n+\t\t\t\trte_eth_dev_socket_id(portid),\n+\t\t\t\tNULL);\n+\t\t}\n+\t\tif (ret < 0)\n+\t\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\"rte_eth_tx_queue_setup:err=%d, port=%u\\n\",\n+\t\t\t\tret, (unsigned) portid);\n+\t}\n+\n+\t/* create a ethtool proxy thread */\n+\tpthread_attr_t attr;\n+\tcpu_set_t cpus;\n+\tpthread_t ethtool_thread;\n+\tstruct nic_info info;\n+\n+\t/* set core affinity to core 1 */\n+\tCPU_ZERO(&cpus);\n+\tCPU_SET(2, &cpus);\n+\tpthread_attr_init(&attr);\n+\tpthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpus);\n+\t/* Since the register size is more than 4K (1147*4) */\n+\tpthread_attr_setstacksize(&attr, 4*PAGE_SIZE);\n+\n+\tinfo.num_of_ports = nb_ports;\n+\tinfo.port_mask = l2fwd_enabled_port_mask;\n+\tif (pthread_create(&ethtool_thread, NULL, &ethtool, &info)) {\n+\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\"Fail to create a pthread for ethtool task!!!\\n\");\n+\t}\n+\tmemset(&port_statistics, 0, sizeof(port_statistics));\n+\n+\tif (!nb_ports_available) {\n+\t\trte_exit(EXIT_FAILURE,\n+\t\t\"All available ports are disabled. Please set portmask.\\n\");\n+\t}\n+\n+\tcheck_all_ports_link_status(nb_ports, l2fwd_enabled_port_mask);\n+\n+\t/* launch per-lcore init on every lcore */\n+\trte_eal_mp_remote_launch(l2fwd_launch_one_lcore, NULL, CALL_MASTER);\n+\tRTE_LCORE_FOREACH_SLAVE(lcore_id) {\n+\t\tif (rte_eal_wait_lcore(lcore_id) < 0)\n+\t\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\ndiff --git a/examples/l2fwd-ethtool/l2fwd-app/netdev_api.h b/examples/l2fwd-ethtool/l2fwd-app/netdev_api.h\nnew file mode 100644\nindex 0000000..0964bea\n--- /dev/null\n+++ b/examples/l2fwd-ethtool/l2fwd-app/netdev_api.h\n@@ -0,0 +1,769 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2015 Intel Corporation. All rights reserved.\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+#ifndef _NETDEV_API_H_\n+#define _NETDEV_API_H_\n+\n+#include <linux/ethtool.h>\n+#include <string.h>\n+#include \"shared_fifo.h\"\n+\n+#define MAC_ADDR_SIZE 6\n+#define quad_aligned_size(x) ((x & 0x7) ? ((x+7)&0x7) : x)\n+\n+#define size16(data_type) (uint16_t)(sizeof(data_type))\n+\n+/* NETDEV_STATUS = 0 if successful */\n+#define NETDEV_UNSUPPORTED -1\n+#define NETDEV_INVALID -1\n+#define NETDEV_STATUS(data_size) (GOOD_RETURN(data_size) \\\n+\t\t\t\t? 0 : NETDEV_INVALID)\n+#define UNUSED(x) (void)(x)\n+\n+#ifdef NETDEV_OP_REQUEST\n+static uint16_t\n+next_reqid(void) {\n+\tstatic uint16_t request_id;\n+\n+\treturn request_id++;\n+}\n+\n+/*\n+ * send request (with one or two variables) to request-pipe\n+ * (invoked by non- DPDK process)\n+ */\n+static int\n+send_request(uint16_t req_id, uint8_t req_type, uint16_t param_size,\n+\tvoid *param_data)\n+{\n+\tint fd;\n+\tuint32_t req[2];\n+\n+\treq[0] = REQ_DWORD_LO(req_id, 0, req_type);\n+\treq[1] = REQ_DWORD_HI(param_size, 0);\n+\n+\tfd = open(REQ_PIPE, O_WRONLY);\n+\twrite(fd, req, PIPE_CTL_BYTE_COUNT);\n+\tif (param_size)\n+\t\twrite(fd, param_data, param_size);\n+\tclose(fd);\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * send request (with more than two variables) to request-pipe\n+ * (invoked by non- DPDK process)\n+ */\n+static int\n+send_request2(uint16_t req_id, uint8_t req_type, uint16_t param1_size,\n+\tvoid *param1_data, int param2_size, void *param2_data)\n+{\n+\tint fd;\n+\tuint32_t req[2];\n+\n+\treq[0] = REQ_DWORD_LO(req_id, 1, req_type);\n+\treq[1] = REQ_DWORD_HI(param1_size, param2_size);\n+\n+\tfd = open(REQ_PIPE, O_WRONLY);\n+\twrite(fd, req, PIPE_CTL_BYTE_COUNT);\n+\n+\tif (param1_size)\n+\t\twrite(fd, param1_data, param1_size);\n+\tif (param2_size)\n+\t\twrite(fd, param2_data, param2_size);\n+\tclose(fd);\n+\n+\treturn 0;\n+}\n+\n+/* read return variables from the reply-pipe (invoked by non- DPDK process) */\n+static int\n+read_reply(uint16_t expected_id, uint16_t *byte_count, void *reply_data1,\n+\tvoid *reply_data2)\n+{\n+\tint fd;\n+\tuint32_t req[2];\n+\tuint16_t rx_id, data1_size;\n+\n+\t/* block on read if reply is not available */\n+\tfd = open(REP_PIPE, O_RDONLY);\n+\tread(fd, req, PIPE_CTL_BYTE_COUNT);\n+\n+\t*byte_count = REP_DATA1_COUNT(req);\n+\trx_id = REP_ID(req);\n+\n+\tif (!GOOD_RETURN(*byte_count)) {\n+\t\tclose(fd);\n+\t\treturn -1;\n+\t}\n+\tdata1_size = BYTE_COUNT((*byte_count));\n+\tread(fd, reply_data1, data1_size);\n+\tif (MULTIPLE_DATA(*byte_count)) {\n+\t\tassert(reply_data2);\n+\t\tread(fd, reply_data2, REP_DATA2_COUNT(req));\n+\t}\n+\tclose(fd);\n+\n+\tif (expected_id != rx_id)\n+\t\treturn -1;\n+\treturn 0;\n+}\n+\n+/* definition of netdev op request */\n+\n+static int\n+netdev_ethtool_get_drvinfo(uint8_t port_id, struct ethtool_drvinfo *drvinfo)\n+{\n+\tuint16_t req_id = next_reqid();\n+\tuint16_t data_size;\n+\n+\tsend_request(req_id, get_drvinfo, 1, &port_id);\n+\tread_reply(req_id, &data_size, drvinfo, NULL);\n+\n+\treturn NETDEV_STATUS(data_size);\n+};\n+\n+static int\n+netdev_ethtool_get_regs_len(uint8_t port_id)\n+{\n+\tuint16_t req_id = next_reqid();\n+\tuint16_t data_size;\n+\tint leng;\n+\n+\tsend_request(req_id, get_regs_len, 1, &port_id);\n+\tread_reply(req_id, &data_size, &leng, NULL);\n+\n+\tif (GOOD_RETURN(data_size))\n+\t\treturn leng;\n+\treturn NETDEV_STATUS(data_size);\n+};\n+\n+static int\n+netdev_ethtool_get_regs(uint8_t port_id, struct ethtool_regs *regs, void *buf)\n+{\n+\tuint16_t req_id = next_reqid();\n+\tuint16_t data_size;\n+\tuint8_t param_data[PARAM_SIZE(struct ethtool_regs)];\n+\n+\tparam_data[0] = port_id;\n+\tmemcpy(FIRST_PARAM(param_data), regs, sizeof(struct ethtool_regs));\n+\n+\tsend_request(req_id, get_regs, PARAM_SIZE(struct ethtool_regs),\n+\t\tparam_data);\n+\tread_reply(req_id, &data_size, regs, buf);\n+\n+\treturn NETDEV_STATUS(data_size);\n+};\n+\n+static int\n+netdev_ethtool_get_link(uint8_t port_id)\n+{\n+\tuint16_t req_id = next_reqid();\n+\tuint16_t data_size;\n+\tint link_status;\n+\n+\tsend_request(req_id, get_link, 1, &port_id);\n+\tread_reply(req_id, &data_size, &link_status, NULL);\n+\tif (GOOD_RETURN(data_size))\n+\t\treturn link_status;\n+\treturn NETDEV_STATUS(data_size);\n+};\n+\n+static int\n+netdev_ethtool_get_eeprom_len(uint8_t port_id)\n+{\n+\tuint16_t req_id = next_reqid();\n+\tuint16_t data_size;\n+\tint leng;\n+\n+\tsend_request(req_id, get_eeprom_len, 1, &port_id);\n+\tread_reply(req_id, &data_size, &leng, NULL);\n+\n+\tif (GOOD_RETURN(data_size))\n+\t\treturn leng;\n+\treturn NETDEV_STATUS(data_size);\n+};\n+\n+static int\n+netdev_ethtool_get_eeprom(uint8_t port_id, struct ethtool_eeprom *eeprom,\n+\tvoid *words)\n+{\n+\tuint16_t req_id = next_reqid();\n+\tuint16_t data_size;\n+\tuint8_t param_data[PARAM_SIZE(struct ethtool_eeprom)];\n+\n+\tparam_data[0] = port_id;\n+\tmemcpy(FIRST_PARAM(param_data), eeprom, sizeof(struct ethtool_eeprom));\n+\n+\tsend_request(req_id, get_eeprom, PARAM_SIZE(struct ethtool_eeprom),\n+\t\tparam_data);\n+\tread_reply(req_id, &data_size, words, NULL);\n+\n+\treturn NETDEV_STATUS(data_size);\n+};\n+\n+static int\n+netdev_ethtool_set_eeprom(uint8_t port_id, struct ethtool_eeprom *eeprom,\n+\tvoid *words)\n+{\n+\tuint16_t req_id = next_reqid();\n+\tuint16_t data_size;\n+\tuint8_t param_data[PARAM_SIZE(struct ethtool_eeprom)];\n+\n+\tparam_data[0] = port_id;\n+\tmemcpy(FIRST_PARAM(param_data), eeprom, sizeof(struct ethtool_eeprom));\n+\n+\tsend_request2(req_id, set_eeprom, PARAM_SIZE(struct ethtool_eeprom),\n+\t\tparam_data, eeprom->len, words);\n+\tread_reply(req_id, &data_size, NULL, NULL);\n+\n+\treturn NETDEV_STATUS(data_size);\n+};\n+\n+static int\n+netdev_ethtool_get_pauseparam(uint8_t port_id, struct ethtool_pauseparam *param)\n+{\n+\tuint16_t req_id = next_reqid();\n+\tuint16_t data_size;\n+\n+\tsend_request(req_id, get_pauseparam, 1, &port_id);\n+\tread_reply(req_id, &data_size, param, NULL);\n+\n+\treturn NETDEV_STATUS(data_size);\n+};\n+\n+static int\n+netdev_ethtool_set_pauseparam(uint8_t port_id, struct ethtool_pauseparam *param)\n+{\n+\tuint16_t req_id = next_reqid();\n+\tuint16_t data_size;\n+\n+\tsend_request(req_id, set_pauseparam, 1, &port_id);\n+\tread_reply(req_id, &data_size, param, NULL);\n+\n+\treturn NETDEV_STATUS(data_size);\n+};\n+\n+static int\n+netdev_net_open(uint8_t port_id) {\n+\tuint16_t req_id = next_reqid();\n+\tuint16_t data_size;\n+\n+\tsend_request(req_id, dev_open, 1, &port_id);\n+\tread_reply(req_id, &data_size, NULL, NULL);\n+\n+\treturn NETDEV_STATUS(data_size);\n+};\n+\n+static int\n+netdev_net_stop(uint8_t port_id) {\n+\tuint16_t req_id = next_reqid();\n+\tuint16_t data_size;\n+\n+\tsend_request(req_id, dev_open, 1, &port_id);\n+\tread_reply(req_id, &data_size, NULL, NULL);\n+\n+\treturn NETDEV_STATUS(data_size);\n+};\n+\n+static int\n+netdev_net_set_rx_mode(uint8_t port_id)\n+{\n+\tuint16_t req_id = next_reqid();\n+\tuint16_t data_size;\n+\n+\tsend_request(req_id, set_rx_mode, 1, &port_id);\n+\tread_reply(req_id, &data_size, NULL, NULL);\n+\n+\treturn NETDEV_STATUS(data_size);\n+};\n+\n+static int\n+netdev_net_get_mac_addr(uint8_t port_id, void *addr)\n+{\n+\tuint16_t req_id = next_reqid();\n+\tuint16_t data_size;\n+\n+\tsend_request(req_id, get_mac_addr, 1, &port_id);\n+\tread_reply(req_id, &data_size, addr, NULL);\n+\n+\treturn NETDEV_STATUS(data_size);\n+};\n+\n+static int\n+netdev_net_set_mac_addr(uint8_t port_id, void *addr)\n+{\n+\tuint16_t req_id = next_reqid();\n+\tuint16_t data_size;\n+\tuint8_t param_data[FIRST_DATA_OFFSET+MAC_ADDR_SIZE];\n+\n+\tparam_data[0] = port_id;\n+\tmemcpy(FIRST_PARAM(param_data), addr, MAC_ADDR_SIZE);\n+\tsend_request(req_id, set_mac_addr,\n+\t\t(FIRST_DATA_OFFSET+MAC_ADDR_SIZE), param_data);\n+\tread_reply(req_id, &data_size, NULL, NULL);\n+\n+\treturn NETDEV_STATUS(data_size);\n+};\n+\n+static int\n+netdev_net_validate_addr(uint8_t port_id, void *addr)\n+{\n+\tuint16_t req_id = next_reqid();\n+\tuint16_t data_size;\n+\tuint8_t param_data[FIRST_DATA_OFFSET+MAC_ADDR_SIZE];\n+\tint valid;\n+\n+\tparam_data[0] = port_id;\n+\tmemcpy(FIRST_PARAM(param_data), addr, MAC_ADDR_SIZE);\n+\tsend_request(req_id, validate_addr,\n+\t\t(FIRST_DATA_OFFSET+MAC_ADDR_SIZE), param_data);\n+\tread_reply(req_id, &data_size, &valid, NULL);\n+\n+\tif (GOOD_RETURN(data_size))\n+\t\treturn valid;\n+\treturn NETDEV_STATUS(data_size);\n+};\n+\n+static int\n+netdev_net_change_mtu(uint8_t port_id, int mtu)\n+{\n+\tuint16_t req_id = next_reqid();\n+\tuint16_t data_size;\n+\tuint8_t param_data[PARAM_SIZE(int)];\n+\n+\tparam_data[0] = port_id;\n+\tmemcpy(FIRST_PARAM(param_data), &mtu, sizeof(int));\n+\tsend_request(req_id, change_mtu, PARAM_SIZE(int), param_data);\n+\tread_reply(req_id, &data_size, NULL, NULL);\n+\n+\treturn NETDEV_STATUS(data_size);\n+};\n+\n+static int\n+netdev_net_get_stats64(uint8_t port_id, void *stats)\n+{\n+\tuint16_t req_id = next_reqid();\n+\tuint16_t data_size;\n+\n+\tsend_request(req_id, get_stats64, 1, &port_id);\n+\tread_reply(req_id, &data_size, stats, NULL);\n+\n+\treturn NETDEV_STATUS(data_size);\n+};\n+\n+static int\n+netdev_net_vlan_rx_add_vid(uint8_t port_id, uint16_t vid)\n+{\n+\tuint16_t req_id = next_reqid();\n+\tuint16_t data_size;\n+\tuint8_t param_data[PARAM_SIZE(int)];\n+\n+\tparam_data[0] = port_id;\n+\tmemcpy(FIRST_PARAM(param_data), &vid, sizeof(uint16_t));\n+\tsend_request(req_id, vlan_rx_add_vid, FIRST_DATA_OFFSET+sizeof(int),\n+\t\tparam_data);\n+\tread_reply(req_id, &data_size, NULL, NULL);\n+\n+\treturn NETDEV_STATUS(data_size);\n+};\n+\n+static int\n+netdev_net_vlan_rx_kill_vid(uint8_t port_id, uint16_t vid)\n+{\n+\tuint16_t req_id = next_reqid();\n+\tuint16_t data_size;\n+\tuint8_t param_data[PARAM_SIZE(int)];\n+\n+\tparam_data[0] = port_id;\n+\tmemcpy(FIRST_PARAM(param_data), &vid, sizeof(uint16_t));\n+\tsend_request(req_id, vlan_rx_kill_vid, FIRST_DATA_OFFSET+sizeof(int),\n+\t\tparam_data);\n+\tread_reply(req_id, &data_size, NULL, NULL);\n+\n+\treturn NETDEV_STATUS(data_size);\n+};\n+\n+#endif /* NETDEV_OP_REQUEST */\n+\n+#ifdef NETDEV_OP_REPLY\n+/* read request from request-pipe (invoked by rte-api server thread) */\n+static int\n+read_request(uint16_t *req_id, uint8_t *req_type, uint16_t *param1_size,\n+\tuint8_t *param1_data, uint16_t *param2_size, void *param2_data)\n+{\n+\tint fd;\n+\tuint32_t req[2];\n+\n+\t/* block on read if request is not sent ... */\n+\tfd = open(REQ_PIPE, O_RDONLY);\n+\tread(fd, req, PIPE_CTL_BYTE_COUNT);\n+\n+\t*req_id\t\t\t= REQ_ID(req);\n+\t*req_type\t\t= REQ_TYPE(req);\n+\t*param1_size\t= REQ_PARAM1_SIZE(req);\n+\n+\tif (*param1_size > 0) {\n+\t\tread(fd, param1_data, *param1_size);\n+\t\tif (REQ_IDTYPE(req)) {\n+\t\t\t*param2_size = REQ_PARAM2_SIZE(req);\n+\t\t\tread(fd, param2_data, *param2_size);\n+\t\t} else\n+\t\t\t*param2_size = 0;\n+\t}\n+\tclose(fd);\n+\n+\treturn 0;\n+}\n+\n+/* definition of netdev op service */\n+/*\n+ * rep[1:0]: request id\n+ * rep[3:2]: data byte count; bit[15]: error status bit[14]: multiple return\n+ *           variables are requested\n+ *\n+ * send reply with one return variable to reply-pipe\n+ * (invoked by rte-api server thread)\n+ */\n+static int\n+send_reply(uint16_t rx_id, uint16_t byte_count, void *reply_data)\n+{\n+\tint fd;\n+\tuint32_t req[2];\n+\n+\treq[0] = REP_DWORD_LO(rx_id, byte_count);\n+\treq[1] = REP_DWORD_HI(0);\n+\n+\tfd = open(REP_PIPE, O_WRONLY);\n+\twrite(fd, req, PIPE_CTL_BYTE_COUNT);\n+\n+\tif (GOOD_RETURN(byte_count) && (byte_count > 0))\n+\t\twrite(fd, reply_data, byte_count);\n+\tclose(fd);\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * send reply with two or more variables to reply-pipe\n+ * (invoked by rte-api server thread)\n+ */\n+static int\n+send_reply2(uint16_t rx_id, uint16_t byte_count1, void *reply_data1,\n+\tuint16_t byte_count2, void *reply_data2)\n+{\n+\tint fd;\n+\tuint32_t req[2];\n+\n+\treq[0] = REP_DWORD_LO(rx_id, REP_MUTILPLE_DATA(byte_count1));\n+\treq[1] = REP_DWORD_HI(byte_count2);\n+\n+\tfd = open(REP_PIPE, O_WRONLY);\n+\twrite(fd, req, PIPE_CTL_BYTE_COUNT);\n+\n+\tif (GOOD_RETURN(byte_count1)  && (byte_count2 > 0)) {\n+\t\twrite(fd, reply_data1, byte_count1);\n+\t\twrite(fd, reply_data2, byte_count2);\n+\t}\n+\tclose(fd);\n+\n+\treturn 0;\n+}\n+\n+/* Functions for netdev service thread */\n+static int\n+proc_ethtool_get_drvinfo(uint8_t port_id, uint16_t req_id, void *param_data)\n+{\n+\tstruct ethtool_drvinfo *drvinfo = param_data;\n+\tuint16_t data_size;\n+\n+\tif (rte_ethtool_get_drvinfo(port_id, drvinfo))\n+\t\tdata_size = STATUS_MASK;\n+\telse\n+\t\tdata_size = size16(struct ethtool_drvinfo);\n+\treturn send_reply(req_id, data_size, param_data);\n+};\n+\n+static int\n+proc_ethtool_get_regs_len(uint8_t port_id, uint16_t req_id)\n+{\n+\tint reg_len;\n+\tuint16_t data_size;\n+\n+\treg_len = rte_ethtool_get_regs_len(port_id);\n+\tif (reg_len == 0)\n+\t\tdata_size = STATUS_MASK;\n+\telse\n+\t\tdata_size = size16(int);\n+\treturn send_reply(req_id, data_size, &reg_len);\n+};\n+\n+static int\n+proc_ethtool_get_regs(uint8_t port_id, uint16_t req_id, void *param_data,\n+\tvoid *reply_data2)\n+{\n+\tstruct ethtool_regs *reg_info = param_data;\n+\tvoid *buf = reply_data2;\n+\tuint16_t data_size;\n+\n+\tif (rte_ethtool_get_regs(port_id, reg_info, buf))\n+\t\tdata_size = STATUS_MASK;\n+\telse\n+\t\tdata_size = rte_ethtool_get_regs_len(port_id)*sizeof(int);\n+\treturn send_reply2(req_id, data_size, reg_info,\n+\t\trte_ethtool_get_regs_len(port_id)*sizeof(int), reply_data2);\n+};\n+\n+static int\n+proc_ethtool_get_link(uint8_t port_id, uint16_t req_id)\n+{\n+\tint link_status;\n+\n+\tlink_status = rte_ethtool_get_link(port_id);\n+\treturn  send_reply(req_id, (uint16_t)sizeof(int), &link_status);\n+};\n+\n+static int\n+proc_ethtool_get_eeprom_len(uint8_t port_id, uint16_t req_id)\n+{\n+\tint eeprom_leng;\n+\tuint16_t data_size;\n+\n+\teeprom_leng = rte_ethtool_get_eeprom_len(port_id);\n+\tif (eeprom_leng == 0)\n+\t\tdata_size = STATUS_MASK;\n+\telse\n+\t\tdata_size = size16(int);\n+\treturn send_reply(req_id, data_size, &eeprom_leng);\n+};\n+\n+static int\n+proc_ethtool_get_eeprom(uint8_t port_id, uint16_t req_id, void *param_data,\n+\tvoid *reply_data)\n+{\n+\tstruct ethtool_eeprom *eeprom_ptr = param_data;\n+\tuint16_t data_size;\n+\n+\tif (rte_ethtool_get_eeprom(port_id, eeprom_ptr, reply_data))\n+\t\tdata_size = STATUS_MASK;\n+\telse\n+\t\tdata_size = (uint16_t)(eeprom_ptr->len & ~1);\n+\treturn send_reply(req_id, data_size, reply_data);\n+};\n+\n+static int\n+proc_ethtool_set_eeprom(uint8_t port_id, uint16_t req_id, void *param_data,\n+\tvoid *param2_data)\n+{\n+\tstruct ethtool_eeprom *eeprom_ptr = param_data;\n+\tuint16_t data_size;\n+\n+\tif (rte_ethtool_set_eeprom(port_id, eeprom_ptr, param2_data))\n+\t\tdata_size = STATUS_MASK;\n+\telse\n+\t\tdata_size = 0;\n+\treturn send_reply(req_id, data_size, &data_size);\n+};\n+\n+static int\n+proc_ethtool_get_pauseparam(uint8_t port_id, uint16_t req_id, void *reply_data)\n+{\n+\tuint16_t data_size;\n+\n+\tif (rte_ethtool_get_pauseparam(port_id,\n+\t\t(struct ethtool_pauseparam *)reply_data))\n+\t\tdata_size = STATUS_MASK;\n+\telse\n+\t\tdata_size = (uint16_t)(sizeof(struct ethtool_pauseparam));\n+\treturn send_reply(req_id, data_size, reply_data);\n+};\n+\n+static int\n+proc_ethtool_set_pauseparam(uint8_t port_id, uint16_t req_id, void *set_data)\n+{\n+\tuint16_t data_size;\n+\n+\tif (rte_ethtool_set_pauseparam(port_id,\n+\t\t(struct ethtool_pauseparam *)set_data))\n+\t\tdata_size = STATUS_MASK;\n+\telse\n+\t\tdata_size = (uint16_t)(sizeof(struct ethtool_pauseparam));\n+\treturn send_reply(req_id, data_size, set_data);\n+};\n+\n+static int\n+proc_net_open(uint8_t port_id, uint16_t req_id)\n+{\n+\tuint16_t data_size;\n+\n+\tif (rte_ethtool_net_open(port_id))\n+\t\tdata_size = STATUS_MASK;\n+\telse\n+\t\tdata_size = 0;\n+\n+\treturn send_reply(req_id, data_size, &data_size);\n+};\n+\n+static int\n+proc_net_stop(uint8_t port_id, uint16_t req_id)\n+{\n+\tuint16_t data_size;\n+\n+\trte_ethtool_net_stop(port_id);\n+\tdata_size = 0;\n+\n+\treturn send_reply(req_id, data_size, &data_size);\n+};\n+\n+static int\n+proc_net_set_rx_mode(uint8_t port_id, uint16_t req_id)\n+{\n+\tuint16_t data_size;\n+\n+\tif (rte_ethtool_net_set_rx_mode(port_id))\n+\t\tdata_size = STATUS_MASK;\n+\telse\n+\t\tdata_size = 0;\n+\n+\treturn send_reply(req_id, data_size, &data_size);\n+};\n+\n+static int\n+proc_net_get_mac_addr(uint8_t port_id, uint16_t req_id, void *param_data)\n+{\n+\tuint16_t data_size;\n+\n+\tif (rte_ethtool_net_get_mac_addr(port_id, param_data))\n+\t\tdata_size = STATUS_MASK;\n+\telse\n+\t\tdata_size = MAC_ADDR_SIZE;\n+\n+\treturn send_reply(req_id, data_size, param_data);\n+};\n+\n+static int\n+proc_net_set_mac_addr(uint8_t port_id, uint16_t req_id, void *param_data)\n+{\n+\tuint16_t data_size;\n+\n+\tif (rte_ethtool_net_set_mac_addr(port_id, param_data))\n+\t\tdata_size = STATUS_MASK;\n+\telse\n+\t\tdata_size = 0;\n+\n+\treturn send_reply(req_id, data_size, &data_size);\n+};\n+\n+static int\n+proc_net_validate_addr(uint8_t port_id, uint16_t req_id, void *param_data)\n+{\n+\tint status;\n+\n+\tstatus = rte_ethtool_net_validate_addr(port_id, param_data);\n+\n+\treturn send_reply(req_id, (uint16_t)sizeof(int), &status);\n+};\n+\n+static int\n+proc_net_set_config(uint8_t port_id, uint16_t req_id, void *param_data)\n+{\n+\tuint16_t data_size;\n+\n+\tif (rte_ethtool_net_set_config(port_id, param_data))\n+\t\tdata_size = STATUS_MASK;\n+\telse\n+\t\tdata_size = 0;\n+\n+\treturn send_reply(req_id, data_size, &data_size);\n+};\n+\n+static int\n+proc_net_change_mtu(uint8_t port_id, uint16_t req_id, void *param_data)\n+{\n+\tuint16_t data_size;\n+\tint mtu = *(int *)(param_data);\n+\n+\tif (rte_ethtool_net_change_mtu(port_id, mtu))\n+\t\tdata_size = STATUS_MASK;\n+\telse\n+\t\tdata_size = 0;\n+\n+\treturn send_reply(req_id, data_size, &data_size);\n+};\n+\n+static int\n+proc_net_get_stats64(uint8_t port_id, uint16_t req_id, void *reply_data)\n+{\n+\tuint16_t data_size;\n+\n+\tif (rte_ethtool_net_get_stats64(port_id, reply_data))\n+\t\tdata_size = STATUS_MASK;\n+\telse\n+\t\tdata_size = size16(struct rte_eth_stats);\n+\n+\treturn send_reply(req_id, data_size, reply_data);\n+};\n+\n+static int\n+proc_net_vlan_rx_add_vid(uint8_t port_id, uint16_t req_id,\n+\tvoid *param_data)\n+{\n+\tuint16_t data_size;\n+\tint *vid_ptr = (int *)param_data;\n+\n+\tif (rte_ethtool_net_vlan_rx_add_vid(port_id, *vid_ptr))\n+\t\tdata_size = STATUS_MASK;\n+\telse\n+\t\tdata_size = 0;\n+\n+\treturn send_reply(req_id, data_size, &data_size);\n+};\n+\n+static int\n+proc_net_vlan_rx_kill_vid(uint8_t port_id, uint16_t req_id,\n+\tvoid *param_data)\n+{\n+\tuint16_t data_size;\n+\tint *vid_ptr = (int *)param_data;\n+\n+\tif (rte_ethtool_net_vlan_rx_kill_vid(port_id, *vid_ptr))\n+\t\tdata_size = STATUS_MASK;\n+\telse\n+\t\tdata_size = 0;\n+\n+\treturn send_reply(req_id, data_size, &data_size);\n+};\n+\n+#endif /* NETDEV_OP_REPLY */\n+#endif /* _NETDEV_API_H_ */\ndiff --git a/examples/l2fwd-ethtool/l2fwd-app/shared_fifo.h b/examples/l2fwd-ethtool/l2fwd-app/shared_fifo.h\nnew file mode 100644\nindex 0000000..82dd962\n--- /dev/null\n+++ b/examples/l2fwd-ethtool/l2fwd-app/shared_fifo.h\n@@ -0,0 +1,158 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2015 Intel Corporation. All rights reserved.\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+#ifndef _SHARED_FIFO_H_\n+#define _SHARED_FIFO_H_\n+\n+#include <stdio.h>\n+#include <stdlib.h>\n+#include <unistd.h>\n+#include <sys/types.h>\n+#include <sys/stat.h>\n+#include <fcntl.h>\n+#include <assert.h>\n+\n+#define REQ_PIPE \"/tmp/nic_request\"\n+#define REP_PIPE \"/tmp/nic_reply\"\n+#define PAGE_SIZE (4*1024)\n+#define STACK_SIZE (4*PAGE_SIZE)\n+#define MAXI_DATA (1024*6)\n+#define MAXI_PARA 1024\n+#define STATUS_MASK 0x8000\n+#define MULTIPLE_DATA_MASK 0x4000\n+#define MAXI_REQ_TYPE 16\n+#define FIRST_DATA_OFFSET 8\n+#define to_ptr(new_ptr_type, data, offset) \\\n+\t(new_ptr_type)(&((unsigned char *)(void *)data)[offset])\n+#define u8ptr(x) (uint8_t *)((void *)x)\n+\n+\n+/*\n+ * req[1:0]:\trequest-id\n+ * req[2]:\t\trequest-id type\n+ * req[3]:\t\trequest type\n+ * req[4:5]:\tparam1-size\n+ * req[7:6]:\tparam2-size\n+ *\n+ * rep[1:0]\t\treply-id\n+ * rep[3:2]:\tdata1-size\t// bit[15]: status bit[14]: two return data\n+ * rep[7:4]:\tdata2-size\n+ */\n+#define PIPE_CTL_BYTE_COUNT (sizeof(uint32_t)*2)\n+#define REQ_DWORD_LO(req_id, id_type, req_tye) \\\n+\t(((uint32_t)req_type << 24) | ((uint32_t)id_type << 16) | req_id)\n+#define REQ_DWORD_HI(param1_size, param2_size) \\\n+\t(((uint32_t)param2_size << 16) | param1_size)\n+\n+#define REP_DWORD_LO(rep_id, data_bytes) \\\n+\t(((uint32_t)data_bytes << 16) | (uint32_t)rep_id)\n+#define REP_DWORD_HI(data2_bytes) (data2_bytes)\n+\n+#define REP_MUTILPLE_DATA(data1_size) (data1_size | MULTIPLE_DATA_MASK)\n+#define REQ_ID(dword_ptr)\t\t(dword_ptr[0] & 0xFFFF)\n+#define REQ_IDTYPE(dword_ptr)\t((dword_ptr[0] >> 16) & 0xFF)\n+#define REQ_TYPE(dword_ptr)\t\t((dword_ptr[0] >> 24) & 0xFF)\n+#define REQ_PARAM1_SIZE(dword_ptr)\t(dword_ptr[1] & 0xFFFF)\n+#define REQ_PARAM2_SIZE(dword_ptr)\t((dword_ptr[1]>>16) & 0xFFFF)\n+#define REP_ID(dword_ptr)\t\t(dword_ptr[0] & 0xFFFF)\n+#define REP_DATA1_COUNT(dword_ptr)\t((dword_ptr[0] >> 16) & 0xFFFF)\n+#define REP_DATA2_COUNT(dword_ptr)\t(dword_ptr[1])\n+\n+#define BAD_RETURN(data_size)\t(data_size | STATUS_MASK)\n+#define GOOD_RETURN(data_size)\t((data_size & STATUS_MASK) == 0)\n+#define MULTIPLE_DATA(data_size)\t(data_size & MULTIPLE_DATA_MASK)\n+#define BYTE_COUNT(data_size)\t\\\n+\t(data_size & ~(STATUS_MASK|MULTIPLE_DATA_MASK))\n+\n+#define PARAM_SIZE(type)\t\t\\\n+\t((uint16_t)(FIRST_DATA_OFFSET+sizeof(type)))\n+#define FIRST_PARAM(param_data)\t(void *)(&(param_data[FIRST_DATA_OFFSET]))\n+#define FIRST_PARAM_TYPE(param_data, ptr_type)\t\\\n+\t(ptr_type)(FIRST_PARAM(param_data))\n+\n+void init_req_pipe(void);\n+void init_rep_pipe(void);\n+\n+struct nic_info {\n+\tuint8_t num_of_ports;\n+\tuint32_t port_mask;\n+\tuint32_t vf_port_mask;\n+\tuint32_t flag;\n+} nic_info;\n+\n+enum req_t {\n+\tget_drvinfo = 0,\n+\tget_setting,\n+\tset_setting,\n+\tget_regs_len,\n+\tget_regs,\n+\tget_link,\n+\tget_eeprom_len,\n+\tget_eeprom,\n+\tset_eeprom,\n+\tget_coalesce,\n+\tset_coalesce,\n+\tget_pauseparam,\n+\tset_pauseparam,\n+\tdump_data,\n+\n+\tdev_open,\n+\tdev_stop,\n+\tset_rx_mode,\n+\tget_mac_addr,\n+\tset_mac_addr,\n+\tvalidate_addr,\n+\tset_config,\n+\tchange_mtu,\n+\tget_stats64,\n+\tget_stats,\n+\tvlan_rx_add_vid,\n+\tvlan_rx_kill_vid,\n+\tipc_begin,\t/* request to start ipc, and get nic info ... */\n+\tipc_end,\t/* request to stop ipc ... */\n+\tinvalid_req,\n+};\n+\n+void\n+init_req_pipe(void)\n+{\n+\tmkfifo(REQ_PIPE, 0666);\n+}\n+\n+void\n+init_rep_pipe(void)\n+{\n+\tmkfifo(REP_PIPE, 0666);\n+}\n+\n+#endif /* _SHARED_FIFO_H_ */\ndiff --git a/examples/l2fwd-ethtool/lib/Makefile b/examples/l2fwd-ethtool/lib/Makefile\nnew file mode 100644\nindex 0000000..b3b8c83\n--- /dev/null\n+++ b/examples/l2fwd-ethtool/lib/Makefile\n@@ -0,0 +1,55 @@\n+#   BSD LICENSE\n+#\n+#   Copyright(c) 2015 Intel Corporation. All rights reserved.\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+ifeq ($(RTE_SDK),)\n+$(error \"Please define RTE_SDK environment variable\")\n+endif\n+\n+# Default target, can be overriden by command line or environment\n+RTE_TARGET ?= x86_64-native-linuxapp-gcc\n+\n+include $(RTE_SDK)/mk/rte.vars.mk\n+\n+ifneq ($(CONFIG_RTE_EXEC_ENV),\"linuxapp\")\n+$(error This application can only operate in a linuxapp environment, \\\n+please change the definition of the RTE_TARGET environment variable)\n+endif\n+\n+# library name\n+LIB = librte_ethtool.a\n+\n+# all source are stored in SRC-Y\n+SRCS-y := rte_ethtool.c\n+\n+CFLAGS += -O3\n+CFLAGS += $(WERROR_FLAGS)\n+\n+include $(RTE_SDK)/mk/rte.extlib.mk\ndiff --git a/examples/l2fwd-ethtool/lib/rte_ethtool.c b/examples/l2fwd-ethtool/lib/rte_ethtool.c\nnew file mode 100644\nindex 0000000..744cb0c\n--- /dev/null\n+++ b/examples/l2fwd-ethtool/lib/rte_ethtool.c\n@@ -0,0 +1,308 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   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 <stdio.h>\n+#include <string.h>\n+#include <stdint.h>\n+#include <rte_version.h>\n+#include <rte_ethdev.h>\n+#include \"rte_ethtool.h\"\n+\n+int\n+rte_ethtool_get_drvinfo(uint8_t port_id, struct ethtool_drvinfo *drvinfo)\n+{\n+\tstruct rte_eth_dev_info dev_info;\n+\tint n;\n+\n+\tmemset(&dev_info, 0, sizeof(dev_info));\n+\trte_eth_dev_info_get(port_id, &dev_info);\n+\n+\tsnprintf(drvinfo->driver, sizeof(drvinfo->driver), \"%s\",\n+\t\tdev_info.driver_name);\n+\tsnprintf(drvinfo->version, sizeof(drvinfo->version), \"%s\",\n+\t\trte_version());\n+\tsnprintf(drvinfo->bus_info, sizeof(drvinfo->bus_info),\n+\t\t\"%04x:%02x:%02x.%x\",\n+\t\tdev_info.pci_dev->addr.domain, dev_info.pci_dev->addr.bus,\n+\t\tdev_info.pci_dev->addr.devid, dev_info.pci_dev->addr.function);\n+\n+\tn = rte_eth_dev_reg_length(port_id);\n+\tif (n > 0)\n+\t\tdrvinfo->regdump_len = n;\n+\telse\n+\t\tdrvinfo->regdump_len = 0;\n+\n+\tn = rte_eth_dev_eeprom_length(port_id);\n+\tif (n > 0)\n+\t\tdrvinfo->eedump_len = n;\n+\telse\n+\t\tdrvinfo->eedump_len = 0;\n+\n+\tdrvinfo->n_stats = sizeof(struct rte_eth_stats) / sizeof(uint64_t);\n+\tdrvinfo->testinfo_len = 0;\n+\n+\treturn 0;\n+}\n+\n+int\n+rte_ethtool_get_regs_len(uint8_t port_id)\n+{\n+\treturn rte_eth_dev_reg_length(port_id);\n+}\n+\n+int\n+rte_ethtool_get_regs(uint8_t port_id, struct ethtool_regs *regs, void *buf)\n+{\n+\tstruct rte_dev_reg_info reg_info;\n+\tint status;\n+\n+\treg_info.buf = buf;\n+\treg_info.leng = 0;\n+\n+\tstatus = rte_eth_dev_reg_info(port_id, &reg_info);\n+\tif (status)\n+\t\treturn status;\n+\tregs->version = reg_info.version;\n+\n+\treturn 0;\n+}\n+\n+int\n+rte_ethtool_get_link(uint8_t port_id)\n+{\n+\tstruct rte_eth_link link;\n+\n+\trte_eth_link_get(port_id, &link);\n+\treturn link.link_status;\n+}\n+\n+int\n+rte_ethtool_get_eeprom_len(uint8_t port_id)\n+{\n+\treturn rte_eth_dev_eeprom_length(port_id);\n+}\n+\n+int\n+rte_ethtool_get_eeprom(uint8_t port_id, struct ethtool_eeprom *eeprom,\n+\tvoid *words)\n+{\n+\tstruct rte_dev_eeprom_info eeprom_info;\n+\tint status;\n+\n+\teeprom_info.offset = eeprom->offset;\n+\teeprom_info.leng = eeprom->len;\n+\teeprom_info.buf = words;\n+\n+\tstatus = rte_eth_dev_get_eeprom(port_id, &eeprom_info);\n+\tif (status)\n+\t\treturn status;\n+\n+\teeprom->magic = eeprom_info.magic;\n+\n+\treturn 0;\n+}\n+\n+int\n+rte_ethtool_set_eeprom(uint8_t port_id, struct ethtool_eeprom *eeprom,\n+\tvoid *words)\n+{\n+\tstruct rte_dev_eeprom_info eeprom_info;\n+\tint status;\n+\n+\teeprom_info.offset = eeprom->offset;\n+\teeprom_info.leng = eeprom->len;\n+\teeprom_info.buf = words;\n+\n+\tstatus = rte_eth_dev_set_eeprom(port_id, &eeprom_info);\n+\tif (status)\n+\t\treturn status;\n+\n+\teeprom->magic = eeprom_info.magic;\n+\n+\treturn 0;\n+}\n+\n+int\n+rte_ethtool_get_pauseparam(uint8_t port_id,\n+\tstruct ethtool_pauseparam *pause_param)\n+{\n+\tstruct rte_eth_fc_conf fc_conf;\n+\tint status;\n+\n+\tstatus = rte_eth_dev_flow_ctrl_get(port_id, &fc_conf);\n+\tif (status)\n+\t\treturn status;\n+\n+\tpause_param->tx_pause = 0;\n+\tpause_param->rx_pause = 0;\n+\tswitch (fc_conf.mode) {\n+\tcase RTE_FC_NONE:\n+\t\t/* dummy block to avoid compiler warning */\n+\t\tbreak;\n+\tcase RTE_FC_RX_PAUSE:\n+\t\tpause_param->rx_pause = 1;\n+\t\tbreak;\n+\tcase RTE_FC_TX_PAUSE:\n+\t\tpause_param->tx_pause = 1;\n+\t\tbreak;\n+\tcase RTE_FC_FULL:\n+\t\tpause_param->rx_pause = 1;\n+\t\tpause_param->tx_pause = 1;\n+\t}\n+\tpause_param->autoneg = (uint32_t)fc_conf.autoneg;\n+\n+\treturn 0;\n+}\n+\n+int\n+rte_ethtool_set_pauseparam(uint8_t port_id,\n+\tstruct ethtool_pauseparam *pause_param)\n+{\n+\tstruct rte_eth_fc_conf fc_conf;\n+\tint status;\n+\t/*\n+\t * Read device flow control parameter first since\n+\t * ethtool set_pauseparam op doesn't have all the information.\n+\t * as defined in struct rte_eth_fc_conf.\n+\t * This API requires the device to support both\n+\t * rte_eth_dev_flow_ctrl_get and rte_eth_dev_flow_ctrl_set, otherwise\n+\t * return -ENOTSUP\n+\t */\n+\tstatus = rte_eth_dev_flow_ctrl_get(port_id, &fc_conf);\n+\tif (status)\n+\t\treturn status;\n+\n+\tfc_conf.autoneg = (uint8_t)pause_param->autoneg;\n+\n+\tif (pause_param->tx_pause) {\n+\t\tif (pause_param->rx_pause)\n+\t\t\tfc_conf.mode = RTE_FC_FULL;\n+\t\telse\n+\t\t\tfc_conf.mode = RTE_FC_TX_PAUSE;\n+\t} else {\n+\t\tif (pause_param->rx_pause)\n+\t\t\tfc_conf.mode = RTE_FC_RX_PAUSE;\n+\t\telse\n+\t\t\tfc_conf.mode = RTE_FC_NONE;\n+\t}\n+\n+\tstatus = rte_eth_dev_flow_ctrl_set(port_id, &fc_conf);\n+\tif (status)\n+\t\treturn status;\n+\n+\treturn 0;\n+}\n+\n+int\n+rte_ethtool_net_open(uint8_t port_id)\n+{\n+\trte_eth_dev_stop(port_id);\n+\n+\treturn rte_eth_dev_start(port_id);\n+}\n+\n+int\n+rte_ethtool_net_stop(uint8_t port_id)\n+{\n+\trte_eth_dev_stop(port_id);\n+\n+\treturn 0;\n+}\n+\n+int\n+rte_ethtool_net_get_mac_addr(uint8_t port_id, struct ether_addr *addr)\n+{\n+\trte_eth_macaddr_get(port_id, addr);\n+\n+\treturn 0;\n+}\n+\n+int\n+rte_ethtool_net_set_mac_addr(uint8_t port_id, struct ether_addr *addr)\n+{\n+\treturn rte_eth_dev_default_mac_addr_set(port_id, addr);\n+}\n+\n+int\n+rte_ethtool_net_validate_addr(uint8_t port_id __rte_unused,\n+\tstruct ether_addr *addr)\n+{\n+\treturn is_valid_assigned_ether_addr(addr);\n+}\n+\n+int\n+rte_ethtool_net_set_config(uint8_t port_id, void *config __rte_unused)\n+{\n+\tstruct rte_eth_link link;\n+\n+\tmemset(&link, 0, sizeof(link));\n+\trte_eth_link_get(port_id, &link);\n+\tif (link.link_status == 1)\n+\t\treturn -EINVAL;\n+\treturn 0;\n+}\n+\n+int\n+rte_ethtool_net_change_mtu(uint8_t port_id, int mtu)\n+{\n+\treturn rte_eth_dev_set_mtu(port_id, (uint16_t)mtu);\n+}\n+\n+int\n+rte_ethtool_net_get_stats64(uint8_t port_id, struct rte_eth_stats *stats)\n+{\n+\treturn rte_eth_stats_get(port_id, stats);\n+}\n+\n+int\n+rte_ethtool_net_vlan_rx_add_vid(uint8_t port_id, uint16_t vid)\n+{\n+\treturn rte_eth_dev_vlan_filter(port_id, vid, 1);\n+}\n+\n+int\n+rte_ethtool_net_vlan_rx_kill_vid(uint8_t port_id, uint16_t vid)\n+{\n+\treturn rte_eth_dev_vlan_filter(port_id, vid, 0);\n+}\n+\n+int\n+rte_ethtool_net_set_rx_mode(uint8_t port_id __rte_unused)\n+{\n+\t/*\n+\t * The set_rx_mode op is part of pmd driver start operation, and\n+\t * the ethdev api maintains software configuration parameters and under-\n+\t * line hardware states consistent, so no operation is needed for\n+\t * rte_ethtool_net_set_rx_mode().\n+\t */\n+\treturn 0;\n+}\ndiff --git a/examples/l2fwd-ethtool/lib/rte_ethtool.h b/examples/l2fwd-ethtool/lib/rte_ethtool.h\nnew file mode 100644\nindex 0000000..dc234be\n--- /dev/null\n+++ b/examples/l2fwd-ethtool/lib/rte_ethtool.h\n@@ -0,0 +1,384 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   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+#ifndef _RTE_ETHTOOL_H_\n+#define _RTE_ETHTOOL_H_\n+\n+/*\n+ * This new interface is designed to provide a user-space shim layer for\n+ * Ethtool and Netdevice op API.\n+ *\n+ * rte_ethtool_get_driver:          ethtool_ops::get_driverinfo\n+ * rte_ethtool_get_link:            ethtool_ops::get_link\n+ * rte_ethtool_get_regs_len:        ethtool_ops::get_regs_len\n+ * rte_ethtool_get_regs:            ethtool_ops::get_regs\n+ * rte_ethtool_get_eeprom_len:      ethtool_ops::get_eeprom_len\n+ * rte_ethtool_get_eeprom:          ethtool_ops::get_eeprom\n+ * rte_ethtool_set_eeprom:          ethtool_ops::set_eeprom\n+ * rte_ethtool_get_pauseparam:      ethtool_ops::get_pauseparam\n+ * rte_ethtool_set_pauseparam:      ethtool_ops::set_pauseparam\n+ *\n+ * rte_ethtool_net_open:            net_device_ops::ndo_open\n+ * rte_ethtool_net_stop:            net_device_ops::ndo_stop\n+ * rte_ethtool_net_set_mac_addr:    net_device_ops::ndo_set_mac_address\n+ * rte_ethtool_net_validate_addr:   net_device_ops::ndo_validate_addr\n+ * rte_ethtool_net_set_config:      net_device_ops::ndo_set_config\n+ * rte_ethtool_net_change_mtu:      net_device_ops::rte_net_change_mtu\n+ * rte_ethtool_net_get_stats64:     net_device_ops::ndo_get_stats64\n+ * rte_ethtool_net_vlan_rx_add_vid  net_device_ops::ndo_vlan_rx_add_vid\n+ * rte_ethtool_net_vlan_rx_kill_vid net_device_ops::ndo_vlan_rx_kill_vid\n+ * rte_ethtool_net_set_rx_mode      net_device_ops::ndo_set_rx_mode\n+ *\n+ */\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+#include <stdint.h>\n+#include <rte_ethdev.h>\n+#include <linux/ethtool.h>\n+\n+/**\n+ * Retrieve the Ethernet device driver information according to attributes described by\n+ * ethtool data structure, ethtool_drvinfo\n+ *\n+ * @param port_id\n+ *   The port identifier of the Ethernet device.\n+ * @param drvinfo\n+ *   A pointer to get driver information\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - others depends on the specific operations implementation.\n+ */\n+int rte_ethtool_get_drvinfo(uint8_t port_id, struct ethtool_drvinfo *drvinfo);\n+\n+/**\n+ * Retrieve the Ethernet device register length in bytes.\n+ *\n+ * @param port_id\n+ *   The port identifier of the Ethernet device.\n+ * @return\n+ *   - (> 0) # of device registers (in bytes) available for dump\n+ *   - (0) no registers available for dump.\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - others depends on the specific operations implementation.\n+ */\n+int rte_ethtool_get_regs_len(uint8_t port_id);\n+\n+/**\n+ * Retrieve the Ethernet device register information according to attributes described by\n+ * ethtool data structure, ethtool_regs\n+ *\n+ * @param port_id\n+ *   The port identifier of the Ethernet device.\n+ * @param reg\n+ *   A pointer to ethtool_regs that has register information\n+ * @param buf\n+ *   A pointer to a buffer that is used to retrieve device register content\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - others depends on the specific operations implementation.\n+ */\n+int rte_ethtool_get_regs(uint8_t port_id, struct ethtool_regs *regs, void *buf);\n+\n+/**\n+ * Retrieve the Ethernet device link status\n+ *\n+ * @param port_id\n+ *   The port identifier of the Ethernet device.\n+ * @return\n+ *   - (1) if link up.\n+ *   - (0) if link down.\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - others depends on the specific operations implementation.\n+ */\n+int rte_ethtool_get_link(uint8_t port_id);\n+\n+/**\n+ * Retrieve the Ethernet device EEPROM size\n+ *\n+ * @param port_id\n+ *   The port identifier of the Ethernet device.\n+ * @return\n+ *\t - (> 0) device EEPROM size in bytes\n+ *   - (0) device has NO EEPROM\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - others depends on the specific operations implementation.\n+ */\n+int rte_ethtool_get_eeprom_len(uint8_t port_id);\n+\n+/**\n+ * Retrieve EEPROM content based upon eeprom range described in ethtool\n+ * data structure, ethtool_eeprom\n+ *\n+ * @param port_id\n+ *   The port identifier of the Ethernet device.\n+ * @param eeprom\n+ *\t The pointer of ethtool_eeprom that provides eeprom range\n+ * @param words\n+ *\t A buffer that holds data read from eeprom\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - others depends on the specific operations implementation.\n+ */\n+int rte_ethtool_get_eeprom(uint8_t port_id, struct ethtool_eeprom *eeprom,\n+\t\t\t      void *words);\n+\n+/**\n+ * Setting EEPROM content based upon eeprom range described in ethtool\n+ * data structure, ethtool_eeprom\n+ *\n+ * @param port_id\n+ *   The port identifier of the Ethernet device.\n+ * @param eeprom\n+ *\t The pointer of ethtool_eeprom that provides eeprom range\n+ * @param words\n+ *\t A buffer that holds data to be written into eeprom\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - others depends on the specific operations implementation.\n+ */\n+int rte_ethtool_set_eeprom(uint8_t port_id, struct ethtool_eeprom *eeprom,\n+\t\t\t      void *words);\n+\n+/**\n+ * Retrieve the Ethernet device pause frame configuration according to\n+ * parameter attributes desribed by ethtool data structure,\n+ * ethtool_pauseparam.\n+ *\n+ * @param port_id\n+ *   The port identifier of the Ethernet device.\n+ * @param pause_param\n+ *\t The pointer of ethtool_coalesce that gets pause frame\n+ *\t configuration parameters\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - others depends on the specific operations implementation.\n+ */\n+int rte_ethtool_get_pauseparam(uint8_t port_id,\n+\t\t\t\t   struct ethtool_pauseparam *pause_param);\n+\n+/**\n+ * Setting the Ethernet device pause frame configuration according to parameter attributes\n+ * desribed by ethtool data structure, ethtool_pauseparam.\n+ *\n+ * @param port_id\n+ *   The port identifier of the Ethernet device.\n+ * @param pause_param\n+ *\t The pointer of ethtool_coalesce that gets ring configuration parameters\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - others depends on the specific operations implementation.\n+ */\n+int rte_ethtool_set_pauseparam(uint8_t port_id,\n+\t\t\t\t   struct ethtool_pauseparam *param);\n+\n+/**\n+ * Start the Ethernet device.\n+ *\n+ * @param port_id\n+ *   The port identifier of the Ethernet device.\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - others depends on the specific operations implementation.\n+ */\n+int rte_ethtool_net_open(uint8_t port_id);\n+\n+/**\n+ * Stop the Ethernet device.\n+ *\n+ * @param port_id\n+ *   The port identifier of the Ethernet device.\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - others depends on the specific operations implementation.\n+ */\n+int rte_ethtool_net_stop(uint8_t port_id);\n+\n+/**\n+ * Get the Ethernet device MAC address.\n+ *\n+ * @param port_id\n+ *   The port identifier of the Ethernet device.\n+ * @param addr\n+ *\t MAC address of the Ethernet device.\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - others depends on the specific operations implementation.\n+ */\n+int rte_ethtool_net_get_mac_addr(uint8_t port_id, struct ether_addr *addr);\n+\n+/**\n+ * Setting the Ethernet device MAC address.\n+ *\n+ * @param port_id\n+ *   The port identifier of the Ethernet device.\n+ * @param addr\n+ *\t The new MAC addr.\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - others depends on the specific operations implementation.\n+ */\n+int rte_ethtool_net_set_mac_addr(uint8_t port_id, struct ether_addr *addr);\n+\n+/**\n+ * Validate if the provided MAC address is valid unicast address\n+ *\n+ * @param port_id\n+ *   The port identifier of the Ethernet device.\n+ * @param addr\n+ *\t A pointer to a buffer (6-byte, 48bit) for the target MAC address\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - others depends on the specific operations implementation.\n+ */\n+int rte_ethtool_net_validate_addr(uint8_t port_id, struct ether_addr *addr);\n+\n+/**\n+ * Setting the Ethernet device configuration.\n+ *\n+ * @param port_id\n+ *   The port identifier of the Ethernet device.\n+ * @param config\n+ *\t A opintr to a configuration parameter.\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - others depends on the specific operations implementation.\n+ */\n+int rte_ethtool_net_set_config(uint8_t port_id, void *config);\n+\n+/**\n+ * Setting the Ethernet device maximum Tx unit.\n+ *\n+ * @param port_id\n+ *   The port identifier of the Ethernet device.\n+ * @param mtu\n+ *\t New MTU\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - others depends on the specific operations implementation.\n+ */\n+int rte_ethtool_net_change_mtu(uint8_t port_id, int mtu);\n+\n+/**\n+ * Retrieve the Ethernet device traffic statistics\n+ *\n+ * @param port_id\n+ *   The port identifier of the Ethernet device.\n+ * @param stats\n+ *\t A pointer to struct rte_eth_stats for statistics parameters\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - others depends on the specific operations implementation.\n+ */\n+int rte_ethtool_net_get_stats64(uint8_t port_id, struct rte_eth_stats *stats);\n+\n+/**\n+ * Update the Ethernet device VLAN filter with new vid\n+ *\n+ * @param port_id\n+ *   The port identifier of the Ethernet device.\n+ * @param vid\n+ *\t A new VLAN id\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - others depends on the specific operations implementation.\n+ */\n+int rte_ethtool_net_vlan_rx_add_vid(uint8_t port_id, uint16_t vid);\n+\n+/**\n+ * Remove VLAN id from Ethernet device.\n+ *\n+ * @param port_id\n+ *   The port identifier of the Ethernet device.\n+ * @param vid\n+ *\t A new VLAN id\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - others depends on the specific operations implementation.\n+ */\n+int rte_ethtool_net_vlan_rx_kill_vid(uint8_t port_id, uint16_t vid);\n+\n+/**\n+ * Setting the Ethernet device rx mode.\n+ *\n+ * @param port_id\n+ *   The port identifier of the Ethernet device.\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - (-ENODEV) if *port_id* invalid.\n+ *   - others depends on the specific operations implementation.\n+ */\n+int rte_ethtool_net_set_rx_mode(uint8_t port_id);\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+#endif /* _RTE_ETHTOOL_H_ */\ndiff --git a/examples/l2fwd-ethtool/nic-control/Makefile b/examples/l2fwd-ethtool/nic-control/Makefile\nnew file mode 100644\nindex 0000000..d49ca98\n--- /dev/null\n+++ b/examples/l2fwd-ethtool/nic-control/Makefile\n@@ -0,0 +1,55 @@\n+#   BSD LICENSE\n+#\n+#   Copyright(c) 2015 Intel Corporation. All rights reserved.\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+ifeq ($(RTE_SDK),)\n+$(error \"Please define RTE_SDK environment variable\")\n+endif\n+\n+# Default target, can be overriden by command line or environment\n+RTE_TARGET ?= x86_64-native-linuxapp-gcc\n+\n+include $(RTE_SDK)/mk/rte.vars.mk\n+\n+ifneq ($(CONFIG_RTE_EXEC_ENV),\"linuxapp\")\n+$(error This application can only operate in a linuxapp environment, \\\n+please change the definition of the RTE_TARGET environment variable)\n+endif\n+\n+# binary name\n+APP = nic-control\n+\n+# all source are stored in SRCS-y\n+SRCS-y := nic_control.c\n+\n+CFLAGS += -O3 -I$(SRCDIR)/../l2fwd-app -I$(SRCDIR)/../lib\n+CFLAGS += $(WERROR_FLAGS)\n+\n+include $(RTE_SDK)/mk/rte.extapp.mk\ndiff --git a/examples/l2fwd-ethtool/nic-control/nic_control.c b/examples/l2fwd-ethtool/nic-control/nic_control.c\nnew file mode 100644\nindex 0000000..f99af58\n--- /dev/null\n+++ b/examples/l2fwd-ethtool/nic-control/nic_control.c\n@@ -0,0 +1,471 @@\n+/*-\n+*   BSD LICENSE\n+*\n+*   Copyright(c) 2015 Intel Corporation. All rights reserved.\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+/*\n+ * This is a non- DPDK application that sends NIC device management request\n+ * through named pipe to a DPDK data plan process.\n+ *\n+ */\n+#define USE_NEW_TYPE\n+#include <stdio.h>\n+#include <stdlib.h>\n+\n+#include <sys/resource.h>\n+\n+#include \"rte_ethtool.h\"\n+#define NETDEV_OP_REQUEST 1\n+#include \"netdev_api.h\"\n+\n+#define PACKET_THD\t100000000\n+#define ITER_LIMIT\t30\n+#define STOP_TIME\t10 /* in seconds */\n+#define CPU_CYCLES\t(double)(2400.0*1000000)\n+\n+#define PACKET_RATE(before_value, after_value, before_ts, after_ts) \\\n+\t((double)(after_value - before_value) * \\\n+\tCPU_CYCLES/(after_ts - before_ts))\n+\n+#define BYTE2BIT_RATE(before_value, after_value, before_ts, after_ts) \\\n+\t((double)(after_value - before_value) * \\\n+\tCPU_CYCLES*8/(after_ts - before_ts))\n+\n+#define PACKET2BIT_RATE(before_value, after_value, before_ts, after_ts) \\\n+\t((double)(after_value - before_value) * \\\n+\tCPU_CYCLES*64*8/(after_ts - before_ts))\n+\n+#define to_mac_type(x) (struct ether_addr *)(void *)(x)\n+\n+struct __time_stamp {\n+\tuint32_t hi;\n+\tuint32_t lo;\n+} time_stamp;\n+\n+static inline unsigned long long\n+rdtsc(void)\n+{\n+\tunsigned hi, lo;\n+\n+\t__asm__ __volatile__ (\"rdtsc\" : \"=a\"(lo), \"=d\"(hi));\n+\treturn ((unsigned long long)lo) | (((unsigned long long)hi) << 32);\n+}\n+\n+static uint32_t port_mask;\n+static uint32_t vf_port_mask;\n+static uint8_t num_of_ports;\n+static int keep_traffic = 1;\n+\n+static inline int\n+is_port_enabled(uint8_t port_id)\n+{\n+\treturn (port_mask & (1 << port_id)) > 0;\n+}\n+\n+static inline int\n+is_vf_port(uint8_t port_id)\n+{\n+\treturn (vf_port_mask & (1 << port_id)) > 0;\n+}\n+\n+static int\n+netdev_ipc_begin(unsigned char *mac_addr)\n+{\n+\tuint8_t reply_data[sizeof(double)];\n+\tuint16_t req_id = next_reqid();\n+\tuint16_t data_size;\n+\tuint32_t reply_data2[2];\n+\tuint8_t param_data[FIRST_DATA_OFFSET+MAC_ADDR_SIZE];\n+\n+\tparam_data[0] = 0;\n+\tmemcpy(FIRST_PARAM(param_data), mac_addr, MAC_ADDR_SIZE);\n+\tsend_request(req_id, ipc_begin,\n+\t\t(FIRST_DATA_OFFSET+MAC_ADDR_SIZE), param_data);\n+\tread_reply(req_id, &data_size, reply_data, reply_data2);\n+\tnum_of_ports = reply_data[0];\n+\tport_mask = reply_data2[0];\n+\tvf_port_mask = reply_data2[1];\n+\treturn reply_data[0];\n+}\n+\n+static int\n+netdev_ipc_end(void)\n+{\n+\tuint8_t reply_data[sizeof(double)];\n+\tuint16_t req_id = next_reqid();\n+\tuint16_t data_size;\n+\n+\tsend_request(req_id, ipc_end, 0, NULL);\n+\tread_reply(req_id, &data_size, reply_data, NULL);\n+\n+\treturn NETDEV_STATUS(data_size);\n+}\n+\n+static void\n+set_stacksize(void)\n+{\n+\tstruct rlimit rl;\n+\tint result;\n+\n+\tresult = getrlimit(RLIMIT_STACK, &rl);\n+\tif (result == 0) {\n+\t\tif (rl.rlim_cur < (const rlim_t)STACK_SIZE) {\n+\t\t\trl.rlim_cur = STACK_SIZE;\n+\t\t\tresult = setrlimit(RLIMIT_STACK, &rl);\n+\t\t\tif (result != 0)\n+\t\t\t\tprintf(\"setrlimit returned result = %d\\n\",\n+\t\t\t\t\tresult);\n+\t\t\telse\n+\t\t\t\tprintf(\"setrlimit succeed!!!\\n\");\n+\t\t} else\n+\t\t\tprintf(\"default stack size is 0x%x\\n\",\n+\t\t\t\t(int)(rl.rlim_cur));\n+\t}\n+}\n+\n+static uint8_t\n+get_port(void)\n+{\n+\tuint8_t port_id;\n+\t/* assume maximum of 32 ports */\n+\tport_id = rand() & 0x1F;\n+\twhile (!is_port_enabled(port_id))\n+\t\tport_id = rand() & 0x1F;\n+\n+\treturn port_id;\n+}\n+\n+static inline char*\n+mac_addr_str(unsigned char *mac_addr)\n+{\n+#define MAC_STR_SIZE (3*MAC_ADDR_SIZE+1)\n+\tstatic char addr_string[MAC_STR_SIZE];\n+\n+\tsnprintf(addr_string, MAC_STR_SIZE, \"%02x:%02x:%02x:%02x:%02x:%02x\",\n+\t\tmac_addr[0], mac_addr[1], mac_addr[2],\n+\t\tmac_addr[3], mac_addr[4], mac_addr[5]);\n+\treturn addr_string;\n+}\n+\n+int\n+main(int argc, char **argv)\n+{\n+\tstruct ethtool_drvinfo drvinfo;\n+\tstruct ethtool_regs regs;\n+\tstruct ethtool_pauseparam pause_param;\n+\tstruct ethtool_eeprom eeprom;\n+\n+\tint8_t reply_data[MAXI_DATA] __attribute__((aligned(8)));\n+\tuint8_t mac_addr[MAC_ADDR_SIZE] = {0x52, 0x54, 0, 0, 0, 0};\n+\tuint8_t mac_base_addr[MAC_ADDR_SIZE] = {0x52, 0x54, 0, 0, 0, 1};\n+\tuint8_t port_id;\n+\tconst int mtu = 1024;\n+\tint iter_count = 0;\n+\tint count, link_up;\n+\tint *int_ptr;\n+\n+\t/* get command parameter */\n+\tif (argc > 1)\n+\t\tkeep_traffic = atoi(argv[1]);\n+\t/* set stack size */\n+\tset_stacksize();\n+\n+\t/* initialize request pipe */\n+\tinit_req_pipe();\n+\n+\tprintf(\"issue ipc begin\\n\");\n+\t/* send a request to start the NIC device */\n+\tnum_of_ports = netdev_ipc_begin(mac_addr);\n+\twhile (num_of_ports == 0)\n+\t\tnum_of_ports = netdev_ipc_begin(mac_addr) & 0xFF;\n+\n+\tfor (port_id = 0; port_id < num_of_ports; port_id++) {\n+\t\tlink_up = netdev_ethtool_get_link(port_id);\n+\t\tprintf(\"port #%d is %s\\n\", port_id, link_up?\"up\":\"down\");\n+\t\tif (!link_up) {\n+\t\t\tif (netdev_net_open(port_id) == 0)\n+\t\t\t\tnetdev_net_set_rx_mode(port_id);\n+\t\t\telse\n+\t\t\t\tprintf(\"failed to start port #%d\\n\", port_id);\n+\t\t}\n+\t}\n+\n+\tmemset(reply_data, 0xFF, MAXI_DATA);\n+\t/* Testing ethtool API */\n+\tfor (port_id = 0; port_id < num_of_ports; port_id++) {\n+\t\tif (!is_port_enabled(port_id))\n+\t\t\tcontinue;\n+\t\telse {\n+\t\t\t/* print out mac address */\n+\t\t\tif (netdev_net_get_mac_addr(port_id, mac_addr)) {\n+\t\t\t\tprintf(\"Fail to get mac addr from port\");\n+\t\t\t\tprintf(\" #%d!!!\\n\", port_id);\n+\t\t\t} else\n+\t\t\t\tprintf(\"\\nPort #%d mac addr is %s\\n\",\n+\t\t\t\t\tport_id, mac_addr_str(mac_addr));\n+\n+\t\t\tif (netdev_ethtool_get_drvinfo(port_id, &drvinfo)) {\n+\t\t\t\tprintf(\"fail to get drvinfo ...\\n\");\n+\t\t\t} else {\n+\t\t\t\tprintf(\"driver: %s version: %s \",\n+\t\t\t\t\tdrvinfo.driver, drvinfo.version);\n+\t\t\t\tprintf(\"fw_version: %s bus_info=%s\\n\",\n+\t\t\t\t\tdrvinfo.fw_version, drvinfo.bus_info);\n+\t\t\t\tprintf(\"reg-size(bytes)=%d eeprom-size=%d\\n\",\n+\t\t\t\t\tdrvinfo.regdump_len,\n+\t\t\t\t\tdrvinfo.eedump_len);\n+\t\t\t}\n+\n+\t\t\tcount = netdev_ethtool_get_regs_len(port_id);\n+\t\t\tif (count <= 0) {\n+\t\t\t\tprintf(\"There are no registers available from\");\n+\t\t\t\tprintf(\" device/port #%d\", port_id);\n+\t\t\t} else {\n+\t\t\t\tprintf(\"Target device has %d registers \",\n+\t\t\t\t\tcount);\n+\t\t\t\tprintf(\"for dump\\n\");\n+\t\t\t}\n+\n+\t\t\tif (count > 0) {\n+\t\t\t\tmemset(&regs, 0xFF,\n+\t\t\t\t\tsizeof(struct ethtool_regs));\n+\t\t\t\tcount = netdev_ethtool_get_regs(port_id,\n+\t\t\t\t\t&regs, reply_data);\n+\t\t\t\tif (count) {\n+\t\t\t\t\tprintf(\"failed to run\");\n+\t\t\t\t\tprintf(\" ethtool_get_regs \");\n+\t\t\t\t\tprintf(\"from port #%d (err=%d)\\n\",\n+\t\t\t\t\t\tport_id, count);\n+\t\t\t\t} else {\n+\t\t\t\t\tint_ptr = (int *)((void *)reply_data);\n+\t\t\t\t\tprintf(\"reg[0]=%x reg[10]=%x \",\n+\t\t\t\t\t\tint_ptr[0], int_ptr[10]);\n+\t\t\t\t\tprintf(\"version=0x%x\\n\",\n+\t\t\t\t\t\tregs.version);\n+\t\t\t\t}\n+\t\t\t}\n+\n+\t\t\t/* Only testing eeprom access over a PF */\n+\t\t\tcount = 0;\n+\t\t\tif (!is_vf_port(port_id)) {\n+\t\t\t\tcount = netdev_ethtool_get_eeprom_len(0);\n+\t\t\t\tif (count == 0) {\n+\t\t\t\t\tprintf(\"fail to retrieve eeprom\");\n+\t\t\t\t\tprintf(\"count from port #%d\\n\",\n+\t\t\t\t\t\tport_id);\n+\t\t\t\t}\n+\t\t\t}\n+\n+\t\t\tif (count) {\n+\t\t\t\tprintf(\"eeprom size is %d bytes\\n\", count);\n+\t\t\t\teeprom.offset = 20;\n+\t\t\t\teeprom.len = 80;\n+\t\t\t\teeprom.magic = 0;\n+\t\t\t\tif (netdev_ethtool_get_eeprom(port_id,\n+\t\t\t\t\t&eeprom, reply_data)) {\n+\t\t\t\t\tprintf(\"Fail to read eeprom\");\n+\t\t\t\t\tprintf(\" from port #%d\\n\",\n+\t\t\t\t\t\tport_id);\n+\t\t\t\t} else {\n+\t\t\t\t\tint i;\n+\t\t\t\t\tuint16_t *word = (uint16_t *)\n+\t\t\t\t\t\t((void *)reply_data);\n+\n+\t\t\t\t\tprintf(\"eeprom-magic: %x;\",\n+\t\t\t\t\t\teeprom.magic);\n+\t\t\t\t\tprintf(\"eeprom data ...\\n\");\n+\t\t\t\t\tcount = 80;\n+\t\t\t\t\tfor (i = 0; i < (int)(eeprom.len\n+\t\t\t\t\t\t>> 1); i++) {\n+\t\t\t\t\t\tif (((i+1) % 16) == 0)\n+\t\t\t\t\t\t\tprintf(\"\\n\");\n+\t\t\t\t\t\tprintf(\"%4x \", word[i]);\n+\t\t\t\t\t}\n+\t\t\t\t\tprintf(\"\\n\");\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t/* testing set/get mac address */\n+\tprintf(\"MAC base address is %s\\n\", mac_addr_str(mac_base_addr));\n+\tfor (port_id = 0; port_id < num_of_ports; port_id++) {\n+\t\tif (netdev_net_get_mac_addr(port_id,\n+\t\t\tto_mac_type(mac_addr)))\n+\t\t\tprintf(\"Fail to get mac addr from port #%d!!!\\n\",\n+\t\t\t\tport_id);\n+\t\telse\n+\t\t\tprintf(\"Port #%d, device mac addr is %s\\n\", port_id,\n+\t\t\t\tmac_addr_str(mac_addr));\n+\n+\t\tif (!netdev_net_validate_addr(port_id,\n+\t\t\tto_mac_type(mac_addr))) {\n+\t\t\tprintf(\"Default mac addr, %s, is not valid\\n\",\n+\t\t\t\tmac_addr_str(mac_addr));\n+\t\t\tstrncpy((char *)mac_addr, (char *)mac_base_addr,\n+\t\t\t\tMAC_ADDR_SIZE);\n+\t\t\tmac_addr[MAC_ADDR_SIZE-1] = 1+port_id;\n+\t\t\tprintf(\"New mac address:%s is used.\\n\",\n+\t\t\t\tmac_addr_str(mac_addr));\n+\n+\t\t\tif (netdev_net_set_mac_addr(port_id,\n+\t\t\t\tto_mac_type(mac_addr)) ||\n+\t\t\t\tnetdev_net_get_mac_addr(port_id,\n+\t\t\t\tto_mac_type(mac_addr))) {\n+\t\t\t\t\tprintf(\"Fail to reset mac addr\");\n+\t\t\t\t\tprintf(\" @ port #%d!!!\\n\", port_id);\n+\t\t\t} else {\n+\t\t\t\tprintf(\"After mac address re-assign\");\n+\t\t\t\tprintf(\" device mac addr is %s\\n\",\n+\t\t\t\t\tmac_addr_str(mac_addr));\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tprintf(\"start nic statistics collection ...\\n\");\n+\n+\tport_id = get_port();\n+\twhile (iter_count++ < ITER_LIMIT) {\n+\t\tuint64_t last_ts, ts;\n+\t\tstruct rte_eth_stats last_stats, stats;\n+\n+\t\tif (netdev_net_get_stats64(port_id, &last_stats)) {\n+\t\t\tprintf(\"Fail to query statistics from port %d\\n\",\n+\t\t\t\tport_id);\n+\t\t\tbreak;\n+\t\t}\n+\t\tlast_ts = rdtsc();\n+\n+\t\tsleep(10);\n+\n+\t\tif (netdev_net_get_stats64(port_id, &stats)) {\n+\t\t\tprintf(\"Fail to query statistics from port %d\\n\",\n+\t\t\t\tport_id);\n+\t\t\tbreak;\n+\t\t}\n+\t\tts = rdtsc();\n+\n+\t\tprintf(\"rx packet rate = %lf, tx packet rate = %lf\\n\",\n+\t\t\tPACKET_RATE(last_stats.ipackets, stats.ipackets,\n+\t\t\tlast_ts, ts),\n+\t\t\tPACKET_RATE(last_stats.opackets, stats.opackets,\n+\t\t\tlast_ts, ts));\n+\n+\n+\t\tprintf(\"rx bit rate = %lf, tx bit rate = %lf\\n\",\n+\t\t\tBYTE2BIT_RATE(last_stats.ibytes, stats.ibytes,\n+\t\t\tlast_ts, ts),\n+\t\t\tBYTE2BIT_RATE(last_stats.obytes, stats.obytes,\n+\t\t\tlast_ts, ts));\n+\n+\t\tsleep(5);\n+\t}\n+\n+\t/* stop link for testing */\n+\tif (!keep_traffic) {\n+\t\tint status;\n+\n+\t\tfor (port_id = 0; port_id < num_of_ports; port_id++) {\n+\t\t\tlink_up = netdev_ethtool_get_link(port_id);\n+\t\t\tif (link_up)\n+\t\t\t\tnetdev_net_stop(port_id);\n+\t\t}\n+\n+\t\tfor (port_id = 0; port_id < num_of_ports; port_id++) {\n+\t\t\tlink_up = netdev_ethtool_get_link(port_id);\n+\t\t\tif (!is_vf_port(port_id) && !link_up) {\n+\t\t\t\teeprom.offset = 20;\n+\t\t\t\teeprom.len = 80;\n+\t\t\t\tif (netdev_ethtool_get_eeprom(port_id,\n+\t\t\t\t\t&eeprom, reply_data)) {\n+\t\t\t\t\tprintf(\"failed to read eeprom\");\n+\t\t\t\t\tprintf(\" break from post-run\");\n+\t\t\t\t\tprintf(\" testing!!!\\n\");\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t\tif (netdev_ethtool_set_eeprom(port_id,\n+\t\t\t\t\t&eeprom, reply_data)) {\n+\t\t\t\t\tprintf(\"Fail to write read-back\");\n+\t\t\t\t\tprintf(\" data to eeprom!!!\\n\");\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t\t/* checking mtu setting */\n+\t\t\t\tif (netdev_net_change_mtu(port_id, mtu)) {\n+\t\t\t\t\tprintf(\"failed to set mtu\");\n+\t\t\t\t\tprintf(\"to %d\\n\", mtu);\n+\t\t\t\t}\n+\n+\t\t\t\t/* add/remove vlan to vid */\n+\t\t\t\tstatus = netdev_net_vlan_rx_add_vid(\n+\t\t\t\t\tport_id, 0);\n+\t\t\t\tif (status == 0) {\n+\t\t\t\t\tstatus = netdev_net_vlan_rx_kill_vid(\n+\t\t\t\t\t\tport_id, 0);\n+\n+\t\t\t\t\tif (status) {\n+\t\t\t\t\t\tprintf(\"fail kill vlan-vid\\n\");\n+\t\t\t\t\t\tbreak;\n+\t\t\t\t\t}\n+\t\t\t\t} else {\n+\t\t\t\t\tprintf(\"fail adding vlan/vid 0\\n\");\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\n+\t\t\t\t/* testing pause parameter get/set functions */\n+\t\t\t\tstatus = netdev_ethtool_get_pauseparam(\n+\t\t\t\t\tport_id, &pause_param);\n+\t\t\t\tif (status) {\n+\t\t\t\t\tprintf(\"get pauseparam fail\\n\");\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t\tprintf(\"pause setup: autoneg: %d \",\n+\t\t\t\t\tpause_param.autoneg);\n+\t\t\t\tprintf(\"tx_pause: %d \",\n+\t\t\t\t\tpause_param.tx_pause);\n+\t\t\t\tprintf(\"rx_pause: %d\\n\",\n+\t\t\t\t\tpause_param.rx_pause);\n+\t\t\t\tstatus = netdev_ethtool_set_pauseparam(\n+\t\t\t\t\tport_id, &pause_param);\n+\t\t\t\tif (status) {\n+\t\t\t\t\tprintf(\"set pause param fail\\n\");\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\twhile (netdev_ipc_end() < 0)\n+\t\t;\n+\n+\tprintf(\"Done for ethtool service request!!!\\n\");\n+\treturn 0;\n+}\n",
    "prefixes": [
        "dpdk-dev",
        "v9",
        "4/5"
    ]
}