[dpdk-dev] [PATCH v3 2/2] virtio/vdev: add a new vdev named eth_cvio
Jianfeng Tan
jianfeng.tan at intel.com
Thu Apr 21 04:56:36 CEST 2016
Add a new virtual device named eth_cvio, it can be used just like
eth_ring, eth_null, etc.
Configured parameters include:
- rx (optional, 1 by default), number of rx, not used for now.
- tx (optional, 1 by default), number of tx, not used for now.
- cq (optional, 0 by default), not supported for now.
- mac (optional), random value will be given if not specified.
- queue_size (optional, 256 by default), size of virtqueue.
- path (madatory), path of vhost, depends on the file type, vhost
user if the given path points to a unix socket; vhost-net if the
given path points to a char device.
- ifname (optional), specify the name of backend tap device; only
valid when backend is vhost-net.
The major difference with original virtio for vm is that, here we use
virtual addr instead of physical addr for vhost to calculate relative
address.
When enable CONFIG_RTE_VIRTIO_VDEV (enabled by default), the compiled
library can be used in both VM and container environment.
Examples:
path_vhost=/dev/vhost-net # use vhost-net as a backend
path_vhost=<path_to_vhost_user> # use vhost-user as a backend
sudo ./examples/l2fwd/build/l2fwd -c 0x100000 -n 4 \
--socket-mem 0,1024 --no-pci --file-prefix=l2fwd \
--vdev=eth_cvio0,mac=00:01:02:03:04:05,path=$path_vhost -- -p 0x1
Known issues:
- Control queue and multi-queue are not supported yet.
- Cannot work with --huge-unlink.
- Cannot work with no-huge.
- Cannot work when there are more than VHOST_MEMORY_MAX_NREGIONS(8)
hugepages.
- Root privilege is a must (mainly becase of sorting hugepages according
to physical address).
- Applications should not use file name like HUGEFILE_FMT ("%smap_%d").
Signed-off-by: Huawei Xie <huawei.xie at intel.com>
Signed-off-by: Jianfeng Tan <jianfeng.tan at intel.com>
Acked-By: Neil Horman <nhorman at tuxdrver.com>
---
doc/guides/nics/overview.rst | 58 +++++-----
doc/guides/rel_notes/release_16_07.rst | 4 +
drivers/net/virtio/rte_eth_virtio_vdev.c | 188 ++++++++++++++++++++++++++++++-
drivers/net/virtio/virtio_ethdev.c | 134 ++++++++++++++--------
drivers/net/virtio/virtio_ethdev.h | 3 +
drivers/net/virtio/virtio_pci.h | 2 +-
drivers/net/virtio/virtio_rxtx.c | 5 +-
drivers/net/virtio/virtio_rxtx_simple.c | 13 ++-
drivers/net/virtio/virtqueue.h | 10 ++
9 files changed, 326 insertions(+), 91 deletions(-)
diff --git a/doc/guides/nics/overview.rst b/doc/guides/nics/overview.rst
index ed116e3..1ff72fb 100644
--- a/doc/guides/nics/overview.rst
+++ b/doc/guides/nics/overview.rst
@@ -74,40 +74,40 @@ Most of these differences are summarized below.
.. table:: Features availability in networking drivers
- ==================== = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
- Feature a b b b c e e e i i i i i i i i i i f f f f m m m n n p r s v v v v x
- f n n o x 1 n n 4 4 4 4 g g x x x x m m m m l l p f u c i z h i i m e
- p x x n g 0 a i 0 0 0 0 b b g g g g 1 1 1 1 x x i p l a n e o r r x n
- a 2 2 d b 0 c e e e e v b b b b 0 0 0 0 4 5 p l p g d s t t n v
- c x x i e 0 . v v f e e e e k k k k e a t i i e i
- k v n . f f . v v . v v t o o t r
- e f g . . . f f . f f a . 3 t
+ ==================== = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+ Feature a b b b c e e e i i i i i i i i i i f f f f m m m n n p r s v v v v x c
+ f n n o x 1 n n 4 4 4 4 g g x x x x m m m m l l p f u c i z h i i m e v
+ p x x n g 0 a i 0 0 0 0 b b g g g g 1 1 1 1 x x i p l a n e o r r x n i
+ a 2 2 d b 0 c e e e e v b b b b 0 0 0 0 4 5 p l p g d s t t n v r
+ c x x i e 0 . v v f e e e e k k k k e a t i i e i t
+ k v n . f f . v v . v v t o o t r i
+ e f g . . . f f . f f a . 3 t o
t v v v v v v 2 v
e e e e e e e
c c c c c c c
- ==================== = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+ ==================== = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
speed capabilities
- link status X X X X X X X X X X X X X X X X X X
+ link status X X X X X X X X X X X X X X X X X X X
link status event X X X X X X X X X X X
queue status event X
Rx interrupt X X X X X X X X X X X X X X X
- queue start/stop X X X X X X X X X X X X X X X X X X
+ queue start/stop X X X X X X X X X X X X X X X X X X X
MTU update X X X X X X X X X X
jumbo frame X X X X X X X X X X X X X X X X X X X X
- scattered Rx X X X X X X X X X X X X X X X X X X X X X
+ scattered Rx X X X X X X X X X X X X X X X X X X X X X X
LRO X X X X
TSO X X X X X X X X X X X X X X X X
- promiscuous mode X X X X X X X X X X X X X X X X X X X X
- allmulticast mode X X X X X X X X X X X X X X X X X X X
- unicast MAC filter X X X X X X X X X X X X X X X X X X X X
- multicast MAC filter X X X X X X X X X X X X X
+ promiscuous mode X X X X X X X X X X X X X X X X X X X X X
+ allmulticast mode X X X X X X X X X X X X X X X X X X X X
+ unicast MAC filter X X X X X X X X X X X X X X X X X X X X X
+ multicast MAC filter X X X X X X X X X X X X X X
RSS hash X X X X X X X X X X X X X X X X X X
RSS key update X X X X X X X X X X X X X X X
RSS reta update X X X X X X X X X X X X X X X
VMDq X X X X X X X
SR-IOV X X X X X X X X X
DCB X X X X X
- VLAN filter X X X X X X X X X X X X X X X X X X
+ VLAN filter X X X X X X X X X X X X X X X X X X X
ethertype filter X X X X X
n-tuple filter X X X
SYN filter X X X
@@ -127,23 +127,23 @@ Most of these differences are summarized below.
inner L4 checksum X X X X X X
packet type parsing X X X X X X X X X X X X X X
timesync X X X X X
- basic stats X X X X X X X X X X X X X X X X X X X X X X X X X X X
- extended stats X X X X X X X X X X X X X X X X X
- stats per queue X X X X X X X X X X X X
+ basic stats X X X X X X X X X X X X X X X X X X X X X X X X X X X X
+ extended stats X X X X X X X X X X X X X X X X X X
+ stats per queue X X X X X X X X X X X X X
EEPROM dump X X X
registers dump X X X X X X
multiprocess aware X X X X X X X X X X X X X X X
- BSD nic_uio X X X X X X X X X X X X X X X X X X X
- Linux UIO X X X X X X X X X X X X X X X X X X X X X X
- Linux VFIO X X X X X X X X X X X X X X X X X X X
+ BSD nic_uio X X X X X X X X X X X X X X X X X X X X
+ Linux UIO X X X X X X X X X X X X X X X X X X X X X X X
+ Linux VFIO X X X X X X X X X X X X X X X X X X X X
other kdrv X X X
- ARMv7 X X X
- ARMv8 X X X
+ ARMv7 X X X X
+ ARMv8 X X X X
Power8 X X X
TILE-Gx X
- x86-32 X X X X X X X X X X X X X X X X X X X X X X X X
- x86-64 X X X X X X X X X X X X X X X X X X X X X X X X X X X
- usage doc X X X X X X X X X
+ x86-32 X X X X X X X X X X X X X X X X X X X X X X X X X
+ x86-64 X X X X X X X X X X X X X X X X X X X X X X X X X X X X
+ usage doc X X X X X X X X X X
design doc
perf doc
- ==================== = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+ ==================== = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
diff --git a/doc/guides/rel_notes/release_16_07.rst b/doc/guides/rel_notes/release_16_07.rst
index 701e827..f26639c 100644
--- a/doc/guides/rel_notes/release_16_07.rst
+++ b/doc/guides/rel_notes/release_16_07.rst
@@ -34,6 +34,10 @@ This section should contain new features added in this release. Sample format:
Refer to the previous release notes for examples.
+* **Virtio support for containers.**
+
+ Add a new virtual device, named eth_cvio, to support virtio for containers.
+
Resolved Issues
---------------
diff --git a/drivers/net/virtio/rte_eth_virtio_vdev.c b/drivers/net/virtio/rte_eth_virtio_vdev.c
index 419acef..282c9ae 100644
--- a/drivers/net/virtio/rte_eth_virtio_vdev.c
+++ b/drivers/net/virtio/rte_eth_virtio_vdev.c
@@ -50,6 +50,8 @@
#include <rte_mbuf.h>
#include <rte_memory.h>
#include <rte_eal_memconfig.h>
+#include <rte_malloc.h>
+#include <rte_kvargs.h>
#include "virtio_pci.h"
#include "virtio_logs.h"
@@ -692,7 +694,7 @@ static uint16_t
vdev_get_queue_num(struct virtio_hw *hw,
uint16_t queue_id __rte_unused)
{
- return hw->queue_num;
+ return hw->queue_size;
}
static void
@@ -832,7 +834,7 @@ vhost_user_backend_setup(struct virtio_hw *hw)
static void
virtio_vdev_init(struct rte_eth_dev_data *data, char *path,
int nb_rx, int nb_tx, int nb_cq __attribute__ ((unused)),
- int queue_num, char *mac, char *ifname)
+ int queue_size, char *mac, char *ifname)
{
int i, r;
struct stat s;
@@ -847,7 +849,7 @@ virtio_vdev_init(struct rte_eth_dev_data *data, char *path,
hw->path = strdup(path);
hw->max_rx_queues = nb_rx;
hw->max_tx_queues = nb_tx;
- hw->queue_num = queue_num;
+ hw->queue_size = queue_size;
hw->mac_specified = 0;
if (mac) {
r = sscanf(mac, "%x:%x:%x:%x:%x:%x", &tmp[0],
@@ -895,3 +897,183 @@ virtio_vdev_uninit(struct rte_eth_dev_data *data)
close(hw->vhostfd);
}
+
+static const char *valid_args[] = {
+#define CVIO_ARG_RX_NUM "rx"
+ CVIO_ARG_RX_NUM,
+#define CVIO_ARG_TX_NUM "tx"
+ CVIO_ARG_TX_NUM,
+#define CVIO_ARG_CQ_NUM "cq"
+ CVIO_ARG_CQ_NUM,
+#define CVIO_ARG_MAC "mac"
+ CVIO_ARG_MAC,
+#define CVIO_ARG_PATH "path"
+ CVIO_ARG_PATH,
+#define CVIO_ARG_QUEUE_SIZE "queue_size"
+ CVIO_ARG_QUEUE_SIZE,
+#define CVIO_ARG_IFNAME "ifname"
+ CVIO_ARG_IFNAME,
+ NULL
+};
+
+#define CVIO_DEF_CQ_EN 0
+#define CVIO_DEF_Q_NUM 1
+#define CVIO_DEF_Q_SZ 256
+
+static int
+get_string_arg(const char *key __rte_unused,
+ const char *value, void *extra_args)
+{
+ if (!value || !extra_args)
+ return -EINVAL;
+
+ *(char **)extra_args = strdup(value);
+
+ return 0;
+}
+
+static int
+get_integer_arg(const char *key __rte_unused,
+ const char *value, void *extra_args)
+{
+ if (!value || !extra_args)
+ return -EINVAL;
+
+ *(uint64_t *)extra_args = strtoull(value, NULL, 0);
+
+ return 0;
+}
+
+static struct rte_eth_dev *
+cvio_eth_dev_alloc(const char *name)
+{
+ struct rte_eth_dev *eth_dev;
+ struct rte_eth_dev_data *data;
+ struct virtio_hw *hw;
+
+ eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL);
+ if (!eth_dev)
+ rte_panic("cannot alloc rte_eth_dev\n");
+
+ data = eth_dev->data;
+
+ hw = rte_zmalloc(NULL, sizeof(*hw), 0);
+ if (!hw)
+ rte_panic("malloc virtio_hw failed\n");
+
+ 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;
+}
+
+/* Dev initialization routine. Invoked once for each virtio vdev at
+ * EAL init time, see rte_eal_dev_init().
+ * Returns 0 on success.
+ */
+static int
+rte_cvio_pmd_devinit(const char *name, const char *params)
+{
+ struct rte_kvargs *kvlist = NULL;
+ struct rte_eth_dev *eth_dev = NULL;
+ uint64_t nb_rx = CVIO_DEF_Q_NUM;
+ uint64_t nb_tx = CVIO_DEF_Q_NUM;
+ uint64_t nb_cq = CVIO_DEF_CQ_EN;
+ uint64_t queue_size = CVIO_DEF_Q_SZ;
+ char *sock_path = NULL;
+ char *mac_addr = NULL;
+ char *ifname = NULL;
+
+ if (!params || params[0] == '\0')
+ rte_panic("arg %s is mandatory for eth_cvio\n",
+ CVIO_ARG_QUEUE_SIZE);
+
+ kvlist = rte_kvargs_parse(params, valid_args);
+ if (!kvlist)
+ rte_panic("error when parsing param\n");
+
+ if (rte_kvargs_count(kvlist, CVIO_ARG_PATH) == 1)
+ rte_kvargs_process(kvlist, CVIO_ARG_PATH,
+ &get_string_arg, &sock_path);
+ else
+ rte_panic("arg %s is mandatory for eth_cvio\n",
+ CVIO_ARG_QUEUE_SIZE);
+
+ if (rte_kvargs_count(kvlist, CVIO_ARG_MAC) == 1)
+ rte_kvargs_process(kvlist, CVIO_ARG_MAC,
+ &get_string_arg, &mac_addr);
+
+ if (rte_kvargs_count(kvlist, CVIO_ARG_IFNAME) == 1)
+ rte_kvargs_process(kvlist, CVIO_ARG_IFNAME,
+ &get_string_arg, &ifname);
+
+ if (rte_kvargs_count(kvlist, CVIO_ARG_QUEUE_SIZE) == 1)
+ rte_kvargs_process(kvlist, CVIO_ARG_QUEUE_SIZE,
+ &get_integer_arg, &queue_size);
+
+ if (rte_kvargs_count(kvlist, CVIO_ARG_RX_NUM) == 1)
+ rte_kvargs_process(kvlist, CVIO_ARG_RX_NUM,
+ &get_integer_arg, &nb_rx);
+
+ if (rte_kvargs_count(kvlist, CVIO_ARG_TX_NUM) == 1)
+ rte_kvargs_process(kvlist, CVIO_ARG_TX_NUM,
+ &get_integer_arg, &nb_tx);
+
+ if (rte_kvargs_count(kvlist, CVIO_ARG_CQ_NUM) == 1)
+ rte_kvargs_process(kvlist, CVIO_ARG_CQ_NUM,
+ &get_integer_arg, &nb_cq);
+
+ eth_dev = cvio_eth_dev_alloc(name);
+
+ virtio_vdev_init(eth_dev->data, sock_path, nb_rx, nb_tx, nb_cq,
+ queue_size, mac_addr, ifname);
+ if (sock_path)
+ free(sock_path);
+ if (mac_addr)
+ free(mac_addr);
+ if (ifname)
+ free(ifname);
+
+ /* originally, this will be called in rte_eal_pci_probe() */
+ eth_virtio_dev_init(eth_dev);
+
+ return 0;
+}
+
+/** Called by rte_eth_dev_detach() */
+static int
+rte_cvio_pmd_devuninit(const char *name)
+{
+ struct rte_eth_dev *eth_dev = NULL;
+
+ if (!name)
+ return -EINVAL;
+
+ PMD_DRV_LOG(INFO, PMD, "Un-Initializing %s\n", name);
+ eth_dev = rte_eth_dev_allocated(name);
+ if (!eth_dev)
+ return -ENODEV;
+
+ /* make sure the device is stopped, queues freed */
+ rte_eth_dev_close(eth_dev->data->port_id);
+
+ virtio_vdev_uninit(eth_dev->data);
+
+ rte_free(eth_dev->data->dev_private);
+ rte_free(eth_dev->data);
+ rte_eth_dev_release_port(eth_dev);
+
+ return 0;
+}
+
+static struct rte_driver rte_cvio_driver = {
+ .name = "eth_cvio",
+ .type = PMD_VDEV,
+ .init = rte_cvio_pmd_devinit,
+ .uninit = rte_cvio_pmd_devuninit,
+};
+
+PMD_REGISTER_DRIVER(rte_cvio_driver);
diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 63a368a..9d28384 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -60,7 +60,6 @@
#include "virtio_rxtx.h"
-static int eth_virtio_dev_init(struct rte_eth_dev *eth_dev);
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);
@@ -168,14 +167,14 @@ virtio_send_command(struct virtqueue *vq, struct virtio_pmd_ctrl *ctrl,
* One RX packet for ACK.
*/
vq->vq_ring.desc[head].flags = VRING_DESC_F_NEXT;
- vq->vq_ring.desc[head].addr = vq->virtio_net_hdr_mz->phys_addr;
+ vq->vq_ring.desc[head].addr = vq->virtio_net_hdr_mem;
vq->vq_ring.desc[head].len = sizeof(struct virtio_net_ctrl_hdr);
vq->vq_free_cnt--;
i = vq->vq_ring.desc[head].next;
for (k = 0; k < pkt_num; k++) {
vq->vq_ring.desc[i].flags = VRING_DESC_F_NEXT;
- vq->vq_ring.desc[i].addr = vq->virtio_net_hdr_mz->phys_addr
+ vq->vq_ring.desc[i].addr = vq->virtio_net_hdr_mem
+ sizeof(struct virtio_net_ctrl_hdr)
+ sizeof(ctrl->status) + sizeof(uint8_t)*sum;
vq->vq_ring.desc[i].len = dlen[k];
@@ -185,7 +184,7 @@ virtio_send_command(struct virtqueue *vq, struct virtio_pmd_ctrl *ctrl,
}
vq->vq_ring.desc[i].flags = VRING_DESC_F_WRITE;
- vq->vq_ring.desc[i].addr = vq->virtio_net_hdr_mz->phys_addr
+ vq->vq_ring.desc[i].addr = vq->virtio_net_hdr_mem
+ sizeof(struct virtio_net_ctrl_hdr);
vq->vq_ring.desc[i].len = sizeof(ctrl->status);
vq->vq_free_cnt--;
@@ -363,20 +362,27 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev,
}
}
- /*
- * Virtio PCI device VIRTIO_PCI_QUEUE_PF register is 32bit,
- * and only accepts 32 bit page frame number.
- * Check if the allocated physical memory exceeds 16TB.
- */
- if ((mz->phys_addr + vq->vq_ring_size - 1) >> (VIRTIO_PCI_QUEUE_ADDR_SHIFT + 32)) {
- PMD_INIT_LOG(ERR, "vring address shouldn't be above 16TB!");
- rte_free(vq);
- return -ENOMEM;
- }
-
memset(mz->addr, 0, sizeof(mz->len));
vq->mz = mz;
- vq->vq_ring_mem = mz->phys_addr;
+ if (dev->dev_type == RTE_ETH_DEV_PCI) {
+ vq->vq_ring_mem = mz->phys_addr;
+
+ /*
+ * Virtio PCI device VIRTIO_PCI_QUEUE_PF register is 32bit,
+ * and only accepts 32 bit page frame number.
+ * Check if the allocated physical memory exceeds 16TB.
+ */
+ if ((mz->phys_addr + vq->vq_ring_size - 1) >>
+ (VIRTIO_PCI_QUEUE_ADDR_SHIFT + 32)) {
+ PMD_INIT_LOG(ERR, "vring address shouldn't be above 16TB!");
+ rte_free(vq);
+ return -ENOMEM;
+ }
+ }
+#ifdef RTE_VIRTIO_VDEV
+ else
+ vq->vq_ring_mem = (phys_addr_t)mz->addr; /* Use vaddr!!! */
+#endif
vq->vq_ring_virt_mem = mz->addr;
PMD_INIT_LOG(DEBUG, "vq->vq_ring_mem: 0x%"PRIx64, (uint64_t)mz->phys_addr);
PMD_INIT_LOG(DEBUG, "vq->vq_ring_virt_mem: 0x%"PRIx64, (uint64_t)(uintptr_t)mz->addr);
@@ -407,7 +413,12 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev,
}
}
vq->virtio_net_hdr_mz = hdr_mz;
- vq->virtio_net_hdr_mem = hdr_mz->phys_addr;
+ if (dev->dev_type == RTE_ETH_DEV_PCI)
+ vq->virtio_net_hdr_mem = hdr_mz->phys_addr;
+#ifdef RTE_VIRTIO_VDEV
+ else
+ vq->virtio_net_hdr_mem = (phys_addr_t)hdr_mz->addr;
+#endif
txr = hdr_mz->addr;
memset(txr, 0, vq_size * sizeof(*txr));
@@ -440,13 +451,24 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev,
return -ENOMEM;
}
}
- vq->virtio_net_hdr_mem =
- vq->virtio_net_hdr_mz->phys_addr;
+ if (dev->dev_type == RTE_ETH_DEV_PCI)
+ vq->virtio_net_hdr_mem = mz->phys_addr;
+#ifdef RTE_VIRTIO_VDEV
+ else
+ vq->virtio_net_hdr_mem = (phys_addr_t)mz->addr;
+#endif
memset(vq->virtio_net_hdr_mz->addr, 0, PAGE_SIZE);
}
hw->vtpci_ops->setup_queue(hw, vq);
+ if (dev->dev_type == RTE_ETH_DEV_PCI)
+ vq->offset = offsetof(struct rte_mbuf, buf_physaddr);
+#ifdef RTE_VIRTIO_VDEV
+ else
+ vq->offset = offsetof(struct rte_mbuf, buf_addr);
+#endif
+
*pvq = vq;
return 0;
}
@@ -499,8 +521,9 @@ virtio_dev_close(struct rte_eth_dev *dev)
virtio_dev_stop(dev);
/* reset the NIC */
- if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)
- vtpci_irq_config(hw, VIRTIO_MSI_NO_VECTOR);
+ if (dev->dev_type == RTE_ETH_DEV_PCI)
+ if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)
+ vtpci_irq_config(hw, VIRTIO_MSI_NO_VECTOR);
vtpci_reset(hw);
virtio_dev_free_mbufs(dev);
virtio_free_queues(dev);
@@ -1002,8 +1025,9 @@ virtio_interrupt_handler(__rte_unused struct rte_intr_handle *handle,
isr = vtpci_isr(hw);
PMD_DRV_LOG(INFO, "interrupt status = %#x", isr);
- if (rte_intr_enable(&dev->pci_dev->intr_handle) < 0)
- PMD_DRV_LOG(ERR, "interrupt enable failed");
+ if (dev->dev_type == RTE_ETH_DEV_PCI)
+ if (rte_intr_enable(&dev->pci_dev->intr_handle) < 0)
+ PMD_DRV_LOG(ERR, "interrupt enable failed");
if (isr & VIRTIO_PCI_ISR_CONFIG) {
if (virtio_dev_link_update(dev, 0) == 0)
@@ -1027,7 +1051,7 @@ rx_func_get(struct rte_eth_dev *eth_dev)
* This function is based on probe() function in virtio_pci.c
* It returns 0 on success.
*/
-static int
+int
eth_virtio_dev_init(struct rte_eth_dev *eth_dev)
{
struct virtio_hw *hw = eth_dev->data->dev_private;
@@ -1057,9 +1081,11 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev)
pci_dev = eth_dev->pci_dev;
- ret = vtpci_init(pci_dev, hw);
- if (ret)
- return ret;
+ if (eth_dev->dev_type == RTE_ETH_DEV_PCI) {
+ ret = vtpci_init(pci_dev, hw);
+ if (ret)
+ return ret;
+ }
/* Reset the device although not necessary at startup */
vtpci_reset(hw);
@@ -1073,10 +1099,12 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev)
return -1;
/* If host does not support status then disable LSC */
- if (!vtpci_with_feature(hw, VIRTIO_NET_F_STATUS))
- pci_dev->driver->drv_flags &= ~RTE_PCI_DRV_INTR_LSC;
+ if (eth_dev->dev_type == RTE_ETH_DEV_PCI) {
+ if (!vtpci_with_feature(hw, VIRTIO_NET_F_STATUS))
+ pci_dev->driver->drv_flags &= ~RTE_PCI_DRV_INTR_LSC;
- rte_eth_copy_pci_info(eth_dev, pci_dev);
+ rte_eth_copy_pci_info(eth_dev, pci_dev);
+ }
rx_func_get(eth_dev);
@@ -1150,15 +1178,17 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev)
PMD_INIT_LOG(DEBUG, "hw->max_rx_queues=%d hw->max_tx_queues=%d",
hw->max_rx_queues, hw->max_tx_queues);
- PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x",
- eth_dev->data->port_id, pci_dev->id.vendor_id,
- pci_dev->id.device_id);
-
- /* Setup interrupt callback */
- if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)
- rte_intr_callback_register(&pci_dev->intr_handle,
- virtio_interrupt_handler, eth_dev);
-
+ if (eth_dev->dev_type == RTE_ETH_DEV_PCI) {
+ PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x",
+ eth_dev->data->port_id, pci_dev->id.vendor_id,
+ pci_dev->id.device_id);
+
+ /* Setup interrupt callback */
+ if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)
+ rte_intr_callback_register(&pci_dev->intr_handle,
+ virtio_interrupt_handler,
+ eth_dev);
+ }
virtio_dev_cq_start(eth_dev);
return 0;
@@ -1190,10 +1220,11 @@ eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev)
eth_dev->data->mac_addrs = NULL;
/* reset interrupt callback */
- if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)
- rte_intr_callback_unregister(&pci_dev->intr_handle,
- virtio_interrupt_handler,
- eth_dev);
+ if (eth_dev->dev_type == RTE_ETH_DEV_PCI)
+ if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)
+ rte_intr_callback_unregister(&pci_dev->intr_handle,
+ virtio_interrupt_handler,
+ eth_dev);
rte_eal_pci_unmap_device(pci_dev);
PMD_INIT_LOG(DEBUG, "dev_uninit completed");
@@ -1258,11 +1289,13 @@ virtio_dev_configure(struct rte_eth_dev *dev)
return -ENOTSUP;
}
- if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)
- if (vtpci_irq_config(hw, 0) == VIRTIO_MSI_NO_VECTOR) {
- PMD_DRV_LOG(ERR, "failed to set config vector");
- return -EBUSY;
- }
+ if (dev->dev_type == RTE_ETH_DEV_PCI) {
+ if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)
+ if (vtpci_irq_config(hw, 0) == VIRTIO_MSI_NO_VECTOR) {
+ PMD_DRV_LOG(ERR, "failed to set config vector");
+ return -EBUSY;
+ }
+ }
return 0;
}
@@ -1431,7 +1464,10 @@ virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
{
struct virtio_hw *hw = dev->data->dev_private;
- dev_info->driver_name = dev->driver->pci_drv.name;
+ if (dev->dev_type == RTE_ETH_DEV_PCI)
+ dev_info->driver_name = dev->driver->pci_drv.name;
+ else
+ dev_info->driver_name = "cvirtio PMD";
dev_info->max_rx_queues = (uint16_t)hw->max_rx_queues;
dev_info->max_tx_queues = (uint16_t)hw->max_tx_queues;
dev_info->min_rx_bufsize = VIRTIO_MIN_RX_BUFSIZE;
diff --git a/drivers/net/virtio/virtio_ethdev.h b/drivers/net/virtio/virtio_ethdev.h
index 3f3b032..284afaa 100644
--- a/drivers/net/virtio/virtio_ethdev.h
+++ b/drivers/net/virtio/virtio_ethdev.h
@@ -113,6 +113,8 @@ uint16_t virtio_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
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);
+
/*
* The VIRTIO_NET_F_GUEST_TSO[46] features permit the host to send us
* frames larger than 1514 bytes. We do not yet support software LRO
@@ -121,4 +123,5 @@ uint16_t virtio_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts,
#define VTNET_LRO_FEATURES (VIRTIO_NET_F_GUEST_TSO4 | \
VIRTIO_NET_F_GUEST_TSO6 | VIRTIO_NET_F_GUEST_ECN)
+
#endif /* _VIRTIO_ETHDEV_H_ */
diff --git a/drivers/net/virtio/virtio_pci.h b/drivers/net/virtio/virtio_pci.h
index 68097e6..3b47332 100644
--- a/drivers/net/virtio/virtio_pci.h
+++ b/drivers/net/virtio/virtio_pci.h
@@ -264,7 +264,7 @@ struct virtio_hw {
#define VHOST_KERNEL 0
#define VHOST_USER 1
int type; /* type of backend */
- uint32_t queue_num;
+ uint32_t queue_size;
char *path;
int mac_specified;
int vhostfd;
diff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c
index ef21d8e..9d7e537 100644
--- a/drivers/net/virtio/virtio_rxtx.c
+++ b/drivers/net/virtio/virtio_rxtx.c
@@ -193,8 +193,7 @@ virtqueue_enqueue_recv_refill(struct virtqueue *vq, struct rte_mbuf *cookie)
start_dp = vq->vq_ring.desc;
start_dp[idx].addr =
- (uint64_t)(cookie->buf_physaddr + RTE_PKTMBUF_HEADROOM
- - hw->vtnet_hdr_size);
+ MBUF_DATA_DMA_ADDR(cookie, vq->offset) - hw->vtnet_hdr_size;
start_dp[idx].len =
cookie->buf_len - RTE_PKTMBUF_HEADROOM + hw->vtnet_hdr_size;
start_dp[idx].flags = VRING_DESC_F_WRITE;
@@ -265,7 +264,7 @@ virtqueue_enqueue_xmit(struct virtqueue *txvq, struct rte_mbuf *cookie,
}
do {
- start_dp[idx].addr = rte_mbuf_data_dma_addr(cookie);
+ start_dp[idx].addr = MBUF_DATA_DMA_ADDR(cookie, txvq->offset);
start_dp[idx].len = cookie->data_len;
start_dp[idx].flags = cookie->next ? VRING_DESC_F_NEXT : 0;
idx = start_dp[idx].next;
diff --git a/drivers/net/virtio/virtio_rxtx_simple.c b/drivers/net/virtio/virtio_rxtx_simple.c
index 8f5293d..599c42e 100644
--- a/drivers/net/virtio/virtio_rxtx_simple.c
+++ b/drivers/net/virtio/virtio_rxtx_simple.c
@@ -80,8 +80,8 @@ virtqueue_enqueue_recv_refill_simple(struct virtqueue *vq,
vq->sw_ring[desc_idx] = cookie;
start_dp = vq->vq_ring.desc;
- start_dp[desc_idx].addr = (uint64_t)((uintptr_t)cookie->buf_physaddr +
- RTE_PKTMBUF_HEADROOM - vq->hw->vtnet_hdr_size);
+ start_dp[desc_idx].addr = MBUF_DATA_DMA_ADDR(cookie, vq->offset) -
+ vq->hw->vtnet_hdr_size;
start_dp[desc_idx].len = cookie->buf_len -
RTE_PKTMBUF_HEADROOM + vq->hw->vtnet_hdr_size;
@@ -119,8 +119,8 @@ virtio_rxq_rearm_vec(struct virtqueue *rxvq)
*(uint64_t *)p = rxvq->mbuf_initializer;
start_dp[i].addr =
- (uint64_t)((uintptr_t)sw_ring[i]->buf_physaddr +
- RTE_PKTMBUF_HEADROOM - rxvq->hw->vtnet_hdr_size);
+ MBUF_DATA_DMA_ADDR(sw_ring[i], rxvq->offset) -
+ rxvq->hw->vtnet_hdr_size;
start_dp[i].len = sw_ring[i]->buf_len -
RTE_PKTMBUF_HEADROOM + rxvq->hw->vtnet_hdr_size;
}
@@ -366,7 +366,7 @@ virtio_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts,
txvq->vq_descx[desc_idx + i].cookie = tx_pkts[i];
for (i = 0; i < nb_tail; i++) {
start_dp[desc_idx].addr =
- rte_mbuf_data_dma_addr(*tx_pkts);
+ MBUF_DATA_DMA_ADDR(*tx_pkts, txvq->offset);
start_dp[desc_idx].len = (*tx_pkts)->pkt_len;
tx_pkts++;
desc_idx++;
@@ -377,7 +377,8 @@ virtio_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts,
for (i = 0; i < nb_commit; i++)
txvq->vq_descx[desc_idx + i].cookie = tx_pkts[i];
for (i = 0; i < nb_commit; i++) {
- start_dp[desc_idx].addr = rte_mbuf_data_dma_addr(*tx_pkts);
+ start_dp[desc_idx].addr =
+ MBUF_DATA_DMA_ADDR(*tx_pkts, txvq->offset);
start_dp[desc_idx].len = (*tx_pkts)->pkt_len;
tx_pkts++;
desc_idx++;
diff --git a/drivers/net/virtio/virtqueue.h b/drivers/net/virtio/virtqueue.h
index 4e9239e..81b5283 100644
--- a/drivers/net/virtio/virtqueue.h
+++ b/drivers/net/virtio/virtqueue.h
@@ -66,6 +66,14 @@ struct rte_mbuf;
#define VIRTQUEUE_MAX_NAME_SZ 32
+#ifdef RTE_VIRTIO_VDEV
+#define MBUF_DATA_DMA_ADDR(mb, offset) \
+ ((uint64_t)((uintptr_t)(*(void **)((uintptr_t)mb + offset)) \
+ + (mb)->data_off))
+#else /* RTE_VIRTIO_VDEV */
+#define MBUF_DATA_DMA_ADDR(mb, offset) rte_mbuf_data_dma_addr(mb)
+#endif /* RTE_VIRTIO_VDEV */
+
#define VTNET_SQ_RQ_QUEUE_IDX 0
#define VTNET_SQ_TQ_QUEUE_IDX 1
#define VTNET_SQ_CQ_QUEUE_IDX 2
@@ -165,6 +173,7 @@ struct virtqueue {
void *vq_ring_virt_mem; /**< linear address of vring*/
unsigned int vq_ring_size;
phys_addr_t vq_ring_mem; /**< physical address of vring */
+ /**< virtual address for vdev. */
struct vring vq_ring; /**< vring keeping desc, used and avail */
uint16_t vq_free_cnt; /**< num of desc available */
@@ -183,6 +192,7 @@ struct virtqueue {
*/
uint16_t vq_used_cons_idx;
uint16_t vq_avail_idx;
+ uint16_t offset; /**< relative offset to obtain addr in mbuf */
uint64_t mbuf_initializer; /**< value to init mbufs. */
phys_addr_t virtio_net_hdr_mem; /**< hdr for each xmit packet */
--
2.1.4
More information about the dev
mailing list