From patchwork Thu Jun 2 03:29:45 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tetsuya Mukawa X-Patchwork-Id: 13157 X-Patchwork-Delegate: yuanhan.liu@linux.intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id 024385691; Thu, 2 Jun 2016 05:30:15 +0200 (CEST) Received: from mail-pa0-f54.google.com (mail-pa0-f54.google.com [209.85.220.54]) by dpdk.org (Postfix) with ESMTP id 91714568B for ; Thu, 2 Jun 2016 05:30:13 +0200 (CEST) Received: by mail-pa0-f54.google.com with SMTP id bz2so2082997pad.1 for ; Wed, 01 Jun 2016 20:30:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=igel-co-jp.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=2xnSq2MR23odUB1IUY8wjYEqDCPvuYVwcnzxqodxrGU=; b=r/5RIaTVkiLFAGdwXqtCQJy760DyRbwCg7XI4n/GWf1373d5k82QxKwgd2VHgGxJut eP08t5ualkwQXe85UEeoq9jFGoC82tOsQKrp7LzZOYIONPz3KQ6WWFfxWv4QXnr1Z4+m WDxrTjkA5Hd4p2AtoqxrihOwiVpJBTNyH9T4DUq+cDn78s7/MhvsAdmYOVYV6FEyiNCa 46ANwRkVjHvBEeFblzLwwSja1Ml+McXdQyUaQ7eGvDOqoj3A6tm8qnSe9w5lOHc2hSui zylXLOivzMErusMM2m6o8mUJgVuo09/r3pXFH7yUUZNG6KDz1W6FTUhfaQIw4Jyuw6X3 JJ3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=2xnSq2MR23odUB1IUY8wjYEqDCPvuYVwcnzxqodxrGU=; b=G6qN92TVyseAiRMACYJx5mVMwp+E0/Xzg6FW6h1JxvewSySmv9BORf+3FkcStwQOiK g1d5IT0BZgqRHiDN7qkmKgJZpa4C/ClmxV7KpAxsSd1Erpx+tWjfJawCuaE6vmXQ4Y4T sZww8glO+qctdjyj9Kb6phY3NzVMIYqvAWJpZhopYfyZldXWcOgHc0Gx+0cw1zeelWug IODHG/2GJyB62xXd2TWdT3PS5LYtn1txWCxq+ewQ2EHxu042KtVQoVUEw9rUb2O9igwq iKTAmI45vc+UZx7F/QW6jo9s7I3lTDNu1koROWcJioph6pP8mzlQBEYPMmHvRS+vMbK+ Jo0A== X-Gm-Message-State: ALyK8tIK9u9JaXc3+PGLSQqMzyaebUXjZyOVJi/uFFZ4tfxDCqkhCV9od/je1pbkiSG70w== X-Received: by 10.66.15.8 with SMTP id t8mr2114079pac.154.1464838212549; Wed, 01 Jun 2016 20:30:12 -0700 (PDT) Received: from localhost.localdomain (napt.igel.co.jp. [219.106.231.132]) by smtp.gmail.com with ESMTPSA id th5sm59830828pab.31.2016.06.01.20.30.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 01 Jun 2016 20:30:11 -0700 (PDT) From: Tetsuya Mukawa To: dev@dpdk.org Cc: yuanhan.liu@linux.intel.com, jianfeng.tan@intel.com, huawei.xie@intel.com, Tetsuya Mukawa Date: Thu, 2 Jun 2016 12:29:45 +0900 Message-Id: <1464838185-21751-7-git-send-email-mukawa@igel.co.jp> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1464838185-21751-1-git-send-email-mukawa@igel.co.jp> References: <1464838185-21751-1-git-send-email-mukawa@igel.co.jp> In-Reply-To: <1457512409-24403-12-git-send-email-mukawa@igel.co.jp> References: <1457512409-24403-12-git-send-email-mukawa@igel.co.jp> Subject: [dpdk-dev] [PATCH v5 6/6] virtio: Add QTest support for virtio-net PMD X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" The patch adds a new virtio-net PMD configuration that allows the PMD to work on host as if the PMD is in VM. Here is new configuration for virtio-net PMD. - CONFIG_RTE_VIRTIO_QTEST To use this mode, EAL needs map all hugepages as one file. Also the file should be mapped between (1 << 31) and (1 << 44). And start address should be aligned by EAL memory size. To allocate like above, use below '--base-virtaddr' option with appropriate value. If EAL cannot allocate memory like above, the PMD will return error while initialization. In the case, try other values. Later supplement patches will help allocating EAL memory like above. To prepare virtio-net device on host, the users need to invoke QEMU process in special QTest mode. This mode is mainly used for testing QEMU devices from outer process. In this mode, no guest runs. Here is QEMU command line. $ qemu-system-x86_64 \ -machine pc-i440fx-1.4,accel=qtest \ -display none -qtest-log /dev/null \ -qtest unix:/tmp/socket,server \ -netdev type=tap,script=/etc/qemu-ifup,id=net0,queues=1 \ -device virtio-net-pci,netdev=net0,mq=on,disable-modern=false,addr=3 \ -chardev socket,id=chr1,path=/tmp/ivshmem,server \ -device ivshmem,size=1G,chardev=chr1,vectors=1,addr=4 * Should use QEMU-2.6, or above. * QEMU process is needed per port. * virtio-1.0 device are only supported. * The vhost backends like vhost-net and vhost-user can be specified. * In most cases, just using above command is enough, but you can also specify other QEMU virtio-net options like mac address. * Only checked "pc-i440fx-1.4" machine, but may work with other machines. * Should not add "--enable-kvm" to QEMU command line. After invoking QEMU, the PMD can connect to QEMU process using unix domain sockets. Over these sockets, virtio-net and ivshmem in QEMU are probed by the PMD. Here is example of command line. $ testpmd -c f -n 1 -m 1024 --no-pci --base-virtaddr=0x400000000 \ --vdev="eth_virtio_qtest0,qtest=/tmp/socket,ivshmem=/tmp/ivshmem"\ -- --disable-hw-vlan --txqflags=0xf00 -i Please specify same unix domain sockets and memory size in both QEMU and DPDK command lines like above. The share memory size should be power of 2, because ivshmem only accepts such memory size. Signed-off-by: Tetsuya Mukawa --- drivers/net/virtio/Makefile | 1 + drivers/net/virtio/virtio_ethdev.c | 3 +- drivers/net/virtio/virtio_ethdev.h | 1 + drivers/net/virtio/virtio_qtest/qtest.h | 95 +++++ drivers/net/virtio/virtio_qtest/virtio_qtest_dev.c | 393 +++++++++++++++++++++ drivers/net/virtio/virtio_qtest/virtio_qtest_dev.h | 42 +++ drivers/net/virtio/virtqueue.h | 6 +- 7 files changed, 536 insertions(+), 5 deletions(-) create mode 100644 drivers/net/virtio/virtio_qtest/qtest.h create mode 100644 drivers/net/virtio/virtio_qtest/virtio_qtest_dev.c create mode 100644 drivers/net/virtio/virtio_qtest/virtio_qtest_dev.h diff --git a/drivers/net/virtio/Makefile b/drivers/net/virtio/Makefile index 1c86d9d..5933205 100644 --- a/drivers/net/virtio/Makefile +++ b/drivers/net/virtio/Makefile @@ -66,6 +66,7 @@ endif ifeq ($(CONFIG_RTE_VIRTIO_QTEST),y) SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio_qtest/qtest_utils.c SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio_qtest/virtio_qtest_pci.c +SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio_qtest/virtio_qtest_dev.c endif # this lib depends upon: diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index f8972f2..c35d1c0 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -59,7 +59,6 @@ #include "virtqueue.h" #include "virtio_rxtx.h" -static int eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev); static int virtio_dev_configure(struct rte_eth_dev *dev); static int virtio_dev_start(struct rte_eth_dev *dev); static void virtio_dev_stop(struct rte_eth_dev *dev); @@ -1179,7 +1178,7 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev) return 0; } -static int +int eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev) { struct rte_pci_device *pci_dev; diff --git a/drivers/net/virtio/virtio_ethdev.h b/drivers/net/virtio/virtio_ethdev.h index 284afaa..cbb03f5 100644 --- a/drivers/net/virtio/virtio_ethdev.h +++ b/drivers/net/virtio/virtio_ethdev.h @@ -114,6 +114,7 @@ uint16_t virtio_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); int eth_virtio_dev_init(struct rte_eth_dev *eth_dev); +int eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev); /* * The VIRTIO_NET_F_GUEST_TSO[46] features permit the host to send us diff --git a/drivers/net/virtio/virtio_qtest/qtest.h b/drivers/net/virtio/virtio_qtest/qtest.h new file mode 100644 index 0000000..534c5a0 --- /dev/null +++ b/drivers/net/virtio/virtio_qtest/qtest.h @@ -0,0 +1,95 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 IGEL Co., Ltd. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of IGEL Co., Ltd. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _VIRTIO_QTEST_H_ +#define _VIRTIO_QTEST_H_ + +#define QTEST_DRV_NAME "eth_virtio_qtest" +#define QTEST_DEVICE_NUM 2 + +#include +#include + +/* Device information */ +#define VIRTIO_NET_DEVICE_ID 0x1000 +#define VIRTIO_NET_VENDOR_ID 0x1af4 +#define IVSHMEM_DEVICE_ID 0x1110 +#define IVSHMEM_VENDOR_ID 0x1af4 +#define PIIX3_DEVICE_ID 0x7000 +#define PIIX3_VENDOR_ID 0x8086 + +/* ------------------------------------------------------------ + * IO port mapping of qtest guest + * ------------------------------------------------------------ + * 0x0000 - 0xbfff : not used + * 0xc000 - 0xc03f : virtio-net(BAR0) + * 0xc040 - 0xffff : not used + * + * ------------------------------------------------------------ + * Memory mapping of qtest quest + * ------------------------------------------------------------ + * 0x00000000_00000000 - 0x00000000_3fffffff : not used + * 0x00000000_40000000 - 0x00000000_40000fff : virtio-net(BAR1) + * 0x00000000_40001000 - 0x00000000_40ffffff : not used + * 0x00000000_41000000 - 0x00000000_417fffff : virtio-net(BAR4) + * 0x00000000_41800000 - 0x00000000_41ffffff : not used + * 0x00000000_42000000 - 0x00000000_420000ff : ivshmem(BAR0) + * 0x00000000_42000100 - 0x00000000_42ffffff : not used + * 0x00000000_80000000 - 0xffffffff_ffffffff : ivshmem(BAR2) + * + * We can only specify start address of a region. The region size + * will be defined by the device implementation in QEMU. + * The size will be pow of 2 according to the PCI specification. + * Also, the region start address should be aligned by region size. + * + * BAR2 of ivshmem will be used to mmap DPDK application memory. + * So this address will be dynamically changed, but not to overlap + * others, it should be mmaped between above addresses. Such allocation + * should be done by EAL. + */ +#define VIRTIO_NET_IO_START 0xc000 +#define VIRTIO_NET_MEMORY1_START 0x40000000 +#define VIRTIO_NET_MEMORY2_START 0x41000000 +#define IVSHMEM_MEMORY1_START 0x42000000 +#define IVSHMEM_MEMORY2_START 0x80000000 + +static inline struct rte_pci_id +qtest_get_pci_id_of_virtio_net(void) +{ + struct rte_pci_id id = {VIRTIO_NET_DEVICE_ID, + VIRTIO_NET_VENDOR_ID, PCI_ANY_ID, PCI_ANY_ID}; + + return id; +} + +#endif /* _VIRTIO_QTEST_H_ */ diff --git a/drivers/net/virtio/virtio_qtest/virtio_qtest_dev.c b/drivers/net/virtio/virtio_qtest/virtio_qtest_dev.c new file mode 100644 index 0000000..dec38ff --- /dev/null +++ b/drivers/net/virtio/virtio_qtest/virtio_qtest_dev.c @@ -0,0 +1,393 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 IGEL Co.,Ltd. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of IGEL Co.,Ltd. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include +#include + +#include "../virtio_logs.h" +#include "../virtio_ethdev.h" + +#include "qtest.h" +#include "qtest_utils.h" +#include "virtio_qtest_dev.h" +#include "virtio_qtest_pci.h" + +#define ETH_VIRTIO_NET_ARG_QTEST_PATH "qtest" +#define ETH_VIRTIO_NET_ARG_IVSHMEM_PATH "ivshmem" +#define ETH_VIRTIO_NET_ARG_VIRTIO_NET_ADDR "virtio-net-addr" +#define ETH_VIRTIO_NET_ARG_IVSHMEM_ADDR "ivshmem-addr" + +static const char *valid_qtest_args[] = { + ETH_VIRTIO_NET_ARG_QTEST_PATH, + ETH_VIRTIO_NET_ARG_IVSHMEM_PATH, + ETH_VIRTIO_NET_ARG_VIRTIO_NET_ADDR, + ETH_VIRTIO_NET_ARG_IVSHMEM_ADDR, + NULL +}; + +static int +get_socket_path_arg(const char *key __rte_unused, + const char *value, void *extra_args) +{ + char **p; + + if ((value == NULL) || (extra_args == NULL)) + return -EINVAL; + + p = extra_args; + *p = strdup(value); + + if (*p == NULL) + return -1; + + return 0; +} + +static int +get_pci_addr_arg(const char *key __rte_unused, + const char *value, void *extra_args) +{ + struct rte_pci_addr *addr = extra_args; + + if ((value == NULL) || (extra_args == NULL)) + return -EINVAL; + + if (eal_parse_pci_DomBDF(value, addr) != 0) + return -1; + + if (addr->domain != 0) + return -1; + + return 0; +} + +static int +virtio_net_eth_dev_free(struct rte_eth_dev *eth_dev) +{ + struct virtio_hw *hw; + int ret; + + ret = rte_eth_dev_release_port(eth_dev); + if (ret < 0) { + PMD_INIT_LOG(ERR, "cannot release a port\n"); + return -1; + } + + hw = eth_dev->data->dev_private; + rte_free(hw); + + return 0; +} + +static struct rte_eth_dev * +virtio_net_eth_dev_alloc(const char *name) +{ + struct rte_eth_dev *eth_dev; + struct rte_eth_dev_data *data; + struct virtio_hw *hw; + int ret; + + eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL); + if (eth_dev == NULL) { + PMD_INIT_LOG(ERR, "cannot alloc a port\n"); + return NULL; + } + + data = eth_dev->data; + + hw = rte_zmalloc(NULL, sizeof(*hw), 0); + if (hw == NULL) { + PMD_INIT_LOG(ERR, "malloc virtio_hw failed\n"); + ret = rte_eth_dev_release_port(eth_dev); + if (ret < 0) + rte_panic("cannot release a port"); + return NULL; + } + + data->dev_private = hw; + data->numa_node = SOCKET_ID_ANY; + data->kdrv = RTE_KDRV_NONE; + data->dev_flags = RTE_ETH_DEV_DETACHABLE; + eth_dev->pci_dev = NULL; + eth_dev->driver = NULL; + + return eth_dev; +} + +static int +virtio_net_eth_pmd_parse_socket_path(struct rte_kvargs *kvlist, + const char *option, char **path) +{ + int ret; + + if (rte_kvargs_count(kvlist, option) == 1) { + ret = rte_kvargs_process(kvlist, option, + &get_socket_path_arg, path); + if (ret != 0) { + PMD_INIT_LOG(ERR, + "Failed to connect to %s socket", option); + return -1; + } + } else { + PMD_INIT_LOG(ERR, "No argument specified for %s", option); + return -1; + } + + return 0; +} + +static int +virtio_net_eth_pmd_parse_pci_addr(struct rte_kvargs *kvlist, + const char *option, struct rte_pci_addr *addr, + struct rte_pci_addr *default_addr) +{ + int ret; + + if (rte_kvargs_count(kvlist, option) == 1) { + ret = rte_kvargs_process(kvlist, option, + &get_pci_addr_arg, addr); + if (ret != 0) { + PMD_INIT_LOG(ERR, + "Specified invalid address in '%s'", option); + return -1; + } + } else + /* copy default pci address */ + *addr = *default_addr; + + return 0; +} + +static int +virtio_prepare_target_devices(struct qtest_pci_device *devices, + struct rte_kvargs *kvlist) +{ + struct qtest_pci_device *virtio_net, *ivshmem; + struct rte_pci_addr default_addr; + const struct rte_memseg *ms; + int ret; + + ms = rte_eal_get_physmem_layout(); + /* if EAL memory size isn't pow of 2, ivshmem will refuse it */ + if ((ms[0].len & (ms[0].len - 1)) != 0) { + PMD_DRV_LOG(ERR, "memory size must be power of 2\n"); + return -1; + } + + /* EAL memory should be mapped under 16TB */ + if ((uint64_t)ms[0].addr >> (VIRTIO_PCI_QUEUE_ADDR_SHIFT + 32)) { + PMD_DRV_LOG(ERR, "EAL memory shouldn't be mapped above 16TB"); + return -1; + } + + /* EAL memory should be mapped above IVSHMEM_MEMORY2_START */ + if ((uint64_t)ms[0].addr < IVSHMEM_MEMORY2_START) { + PMD_DRV_LOG(ERR, "EAL memory shouldn't be mapped under 0x%x", + IVSHMEM_MEMORY2_START); + return -1; + } + + virtio_net = &devices[0]; + ivshmem = &devices[1]; + + virtio_net->name = "virtio-net"; + virtio_net->device_id = VIRTIO_NET_DEVICE_ID; + virtio_net->vendor_id = VIRTIO_NET_VENDOR_ID; + virtio_net->init = qtest_init_pci_device; + virtio_net->bar[0].addr = PCI_BASE_ADDRESS_0; + virtio_net->bar[0].type = QTEST_PCI_BAR_IO; + virtio_net->bar[0].region_start = VIRTIO_NET_IO_START; + virtio_net->bar[1].addr = PCI_BASE_ADDRESS_1; + virtio_net->bar[1].type = QTEST_PCI_BAR_MEMORY_32; + virtio_net->bar[1].region_start = VIRTIO_NET_MEMORY1_START; + virtio_net->bar[4].addr = PCI_BASE_ADDRESS_4; + virtio_net->bar[4].type = QTEST_PCI_BAR_MEMORY_64; + virtio_net->bar[4].region_start = VIRTIO_NET_MEMORY2_START; + + ivshmem->name = "ivshmem"; + ivshmem->device_id = IVSHMEM_DEVICE_ID; + ivshmem->vendor_id = IVSHMEM_VENDOR_ID; + ivshmem->init = qtest_init_pci_device; + ivshmem->bar[0].addr = PCI_BASE_ADDRESS_0; + ivshmem->bar[0].type = QTEST_PCI_BAR_MEMORY_32; + ivshmem->bar[0].region_start = IVSHMEM_MEMORY1_START; + ivshmem->bar[2].addr = PCI_BASE_ADDRESS_2; + ivshmem->bar[2].type = QTEST_PCI_BAR_MEMORY_64; + /* In host mode, only one memory segment is vaild */ + ivshmem->bar[2].region_start = (uint64_t)ms[0].addr; + + /* + * Set pci addresses specified by command line. + * QTest utils will only check specified pci address. + * If it's wrong, a target device won't be found. + */ + default_addr.domain = 0; + default_addr.bus = 0; + default_addr.function = 0; + + default_addr.devid = 3; + ret = virtio_net_eth_pmd_parse_pci_addr(kvlist, + ETH_VIRTIO_NET_ARG_VIRTIO_NET_ADDR, + &virtio_net->specified_addr, &default_addr); + if (ret < 0) + return -1; + + default_addr.devid = 4; + ret = virtio_net_eth_pmd_parse_pci_addr(kvlist, + ETH_VIRTIO_NET_ARG_IVSHMEM_ADDR, + &ivshmem->specified_addr, &default_addr); + if (ret < 0) + return -1; + + return 0; +} +/* + * Initialization when "CONFIG_RTE_VIRTIO_VDEV_QTEST" is enabled. + */ +static int +rte_qtest_virtio_pmd_init(const char *name, const char *params) +{ + struct rte_kvargs *kvlist; + struct virtio_hw *hw = NULL; + struct rte_eth_dev *eth_dev = NULL; + char *qtest_path = NULL, *ivshmem_path = NULL; + struct qtest_pci_device devices[QTEST_DEVICE_NUM]; + int ret; + + if (params == NULL || params[0] == '\0') + return -EINVAL; + + kvlist = rte_kvargs_parse(params, valid_qtest_args); + if (kvlist == NULL) { + PMD_INIT_LOG(ERR, "error when parsing param"); + return -EFAULT; + } + + ret = virtio_net_eth_pmd_parse_socket_path(kvlist, + ETH_VIRTIO_NET_ARG_IVSHMEM_PATH, &ivshmem_path); + if (ret < 0) + goto error; + + ret = virtio_net_eth_pmd_parse_socket_path(kvlist, + ETH_VIRTIO_NET_ARG_QTEST_PATH, &qtest_path); + if (ret < 0) + goto error; + + ret = virtio_prepare_target_devices(devices, kvlist); + if (ret < 0) + goto error; + + eth_dev = virtio_net_eth_dev_alloc(name); + if (eth_dev == NULL) + goto error; + + hw = eth_dev->data->dev_private; + hw->virtio_user_dev = qtest_vdev_init(qtest_path, ivshmem_path, + devices, QTEST_DEVICE_NUM); + if (hw->virtio_user_dev == NULL) + goto error; + + ret = qtest_vtpci_init(hw, ð_dev->data->dev_flags); + if (ret < 0) + goto error; + + /* originally, this will be called in rte_eal_pci_probe() */ + ret = eth_virtio_dev_init(eth_dev); + if (ret < 0) + goto error; + + eth_dev->driver = NULL; + eth_dev->data->dev_flags |= RTE_ETH_DEV_DETACHABLE; + eth_dev->data->kdrv = RTE_KDRV_NONE; + eth_dev->data->drv_name = QTEST_DRV_NAME; + + free(qtest_path); + free(ivshmem_path); + rte_kvargs_free(kvlist); + return 0; + +error: + if (hw != NULL && hw->virtio_user_dev != NULL) + qtest_vdev_uninit(hw->virtio_user_dev); + if (eth_dev) + virtio_net_eth_dev_free(eth_dev); + if (qtest_path) + free(qtest_path); + if (ivshmem_path) + free(ivshmem_path); + rte_kvargs_free(kvlist); + return -EFAULT; +} + +static int +rte_qtest_virtio_pmd_uninit(const char *name) +{ + struct rte_eth_dev *eth_dev; + struct virtio_hw *hw; + int ret; + + if (name == NULL) + return -EINVAL; + + /* find the ethdev entry */ + eth_dev = rte_eth_dev_allocated(name); + if (eth_dev == NULL) + return -ENODEV; + + ret = eth_virtio_dev_uninit(eth_dev); + if (ret != 0) + return -EFAULT; + + hw = eth_dev->data->dev_private; + qtest_vdev_uninit(hw->virtio_user_dev); + + ret = virtio_net_eth_dev_free(eth_dev); + if (ret != 0) + return -EFAULT; + + return 0; +} + +static struct rte_driver rte_qtest_virtio_driver = { + .name = QTEST_DRV_NAME, + .type = PMD_VDEV, + .init = rte_qtest_virtio_pmd_init, + .uninit = rte_qtest_virtio_pmd_uninit, +}; + +PMD_REGISTER_DRIVER(rte_qtest_virtio_driver); diff --git a/drivers/net/virtio/virtio_qtest/virtio_qtest_dev.h b/drivers/net/virtio/virtio_qtest/virtio_qtest_dev.h new file mode 100644 index 0000000..82f1eec --- /dev/null +++ b/drivers/net/virtio/virtio_qtest/virtio_qtest_dev.h @@ -0,0 +1,42 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 IGEL Co., Ltd. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of IGEL Co., Ltd. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _VIRTIO_QTEST_VDEV_H +#define _VIRTIO_QTEST_VDEV_H + +#include +#include "../virtio_pci.h" + +const struct virtio_pci_ops qtest_ops; + +#endif diff --git a/drivers/net/virtio/virtqueue.h b/drivers/net/virtio/virtqueue.h index 8ffc366..8edb85f 100644 --- a/drivers/net/virtio/virtqueue.h +++ b/drivers/net/virtio/virtqueue.h @@ -66,13 +66,13 @@ struct rte_mbuf; #define VIRTQUEUE_MAX_NAME_SZ 32 -#ifdef RTE_VIRTIO_VDEV +#if defined(RTE_VIRTIO_VDEV) || defined(RTE_VIRTIO_QTEST) #define MBUF_DATA_DMA_ADDR(mb, offset) \ ((uint64_t)((uintptr_t)(*(void **)((uintptr_t)mb + offset)) \ + (mb)->data_off)) -#else /* RTE_VIRTIO_VDEV */ +#else /* RTE_VIRTIO_VDEV or RTE_VIRTIO_QTEST */ #define MBUF_DATA_DMA_ADDR(mb, offset) rte_mbuf_data_dma_addr(mb) -#endif /* RTE_VIRTIO_VDEV */ +#endif /* RTE_VIRTIO_VDEV or RTE_VIRTIO_QTEST */ #define VTNET_SQ_RQ_QUEUE_IDX 0 #define VTNET_SQ_TQ_QUEUE_IDX 1