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), if CQ is enabled, not supported for now.
  - mac (optional), random value will be given if not specified.
  - queue_num (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:
a. Use vhost-net as a backend
sudo numactl -N 1 -m 1 ./examples/l2fwd/build/l2fwd -c 0x100000 -n 4 \
    -m 1024 --no-pci --single-file --file-prefix=l2fwd \
    --vdev=eth_cvio0,mac=00:01:02:03:04:05,path=/dev/vhost-net \
    -- -p 0x1

b. Use vhost-user as a backend
numactl -N 1 -m 1 ./examples/l2fwd/build/l2fwd -c 0x100000 -n 4 -m 1024 \
    --no-pci --single-file --file-prefix=l2fwd \
    --vdev=eth_cvio0,mac=00:01:02:03:04:05,path=<path_to_vhost_user> \
    -- -p 0x1

Signed-off-by: Huawei Xie <huawei.xie at intel.com>
Signed-off-by: Jianfeng Tan <jianfeng.tan at intel.com>
---
 drivers/net/virtio/virtio_ethdev.c      | 329 +++++++++++++++++++++++++-------
 drivers/net/virtio/virtio_rxtx.c        |   6 +-
 drivers/net/virtio/virtio_rxtx_simple.c |  13 +-
 drivers/net/virtio/virtqueue.h          |  15 +-
 4 files changed, 282 insertions(+), 81 deletions(-)

diff --git a/drivers/net/virtio/virtio_ethdev.c 
b/drivers/net/virtio/virtio_ethdev.c
index 755503d..b790fd0 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -52,6 +52,7 @@
 #include <rte_memory.h>
 #include <rte_eal.h>
 #include <rte_dev.h>
+#include <rte_kvargs.h>

 #include "virtio_ethdev.h"
 #include "virtio_pci.h"
@@ -170,14 +171,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];
@@ -187,7 +188,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--;
@@ -366,70 +367,85 @@ 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;
        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);
+
+       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.
+                */
+               uint64_t last_physaddr = vq->vq_ring_mem + vq->vq_ring_size - 1;
+
+               if (last_physaddr >> (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
+
+       PMD_INIT_LOG(DEBUG, "vq->vq_ring_mem:      0x%" PRIx64,
+                    (uint64_t)vq->vq_ring_mem);
+       PMD_INIT_LOG(DEBUG, "vq->vq_ring_virt_mem: 0x%" PRIx64,
+                    (uint64_t)(uintptr_t)vq->vq_ring_virt_mem);
        vq->virtio_net_hdr_mz  = NULL;
        vq->virtio_net_hdr_mem = 0;

+       uint64_t hdr_size = 0;
        if (queue_type == VTNET_TQ) {
                /*
                 * For each xmit packet, allocate a virtio_net_hdr
                 */
                snprintf(vq_name, sizeof(vq_name), "port%d_tvq%d_hdrzone",
                        dev->data->port_id, queue_idx);
-               vq->virtio_net_hdr_mz = rte_memzone_reserve_aligned(vq_name,
-                       vq_size * hw->vtnet_hdr_size,
-                       socket_id, 0, RTE_CACHE_LINE_SIZE);
-               if (vq->virtio_net_hdr_mz == NULL) {
-                       if (rte_errno == EEXIST)
-                               vq->virtio_net_hdr_mz =
-                                       rte_memzone_lookup(vq_name);
-                       if (vq->virtio_net_hdr_mz == NULL) {
-                               rte_free(vq);
-                               return -ENOMEM;
-                       }
-               }
-               vq->virtio_net_hdr_mem =
-                       vq->virtio_net_hdr_mz->phys_addr;
-               memset(vq->virtio_net_hdr_mz->addr, 0,
-                       vq_size * hw->vtnet_hdr_size);
+               hdr_size = vq_size * hw->vtnet_hdr_size;
        } else if (queue_type == VTNET_CQ) {
                /* Allocate a page for control vq command, data and status */
                snprintf(vq_name, sizeof(vq_name), "port%d_cvq_hdrzone",
                        dev->data->port_id);
-               vq->virtio_net_hdr_mz = rte_memzone_reserve_aligned(vq_name,
-                       PAGE_SIZE, socket_id, 0, RTE_CACHE_LINE_SIZE);
-               if (vq->virtio_net_hdr_mz == NULL) {
+               hdr_size = PAGE_SIZE;
+       }
+
+       if (hdr_size) { /* queue_type is VTNET_TQ or VTNET_CQ */
+               mz = rte_memzone_reserve_aligned(vq_name, hdr_size, socket_id,
+                                                0, RTE_CACHE_LINE_SIZE);
+               if (!mz) {
                        if (rte_errno == EEXIST)
-                               vq->virtio_net_hdr_mz =
-                                       rte_memzone_lookup(vq_name);
-                       if (vq->virtio_net_hdr_mz == NULL) {
+                               mz = rte_memzone_lookup(vq_name);
+                       if (!mz) {
                                rte_free(vq);
                                return -ENOMEM;
                        }
                }
-               vq->virtio_net_hdr_mem =
-                       vq->virtio_net_hdr_mz->phys_addr;
-               memset(vq->virtio_net_hdr_mz->addr, 0, PAGE_SIZE);
+               vq->virtio_net_hdr_mz = mz;
+               vq->virtio_net_hdr_vaddr = mz->addr;
+               memset(vq->virtio_net_hdr_vaddr, 0, hdr_size);
+
+               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
        }

        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;
 }
@@ -479,8 +495,10 @@ virtio_dev_close(struct rte_eth_dev *dev)
        PMD_INIT_LOG(DEBUG, "virtio_dev_close");

        /* 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);
        hw->started = 0;
        virtio_dev_free_mbufs(dev);
@@ -983,8 +1001,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)
@@ -1037,8 +1056,9 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev)

        pci_dev = eth_dev->pci_dev;

-       if (vtpci_init(pci_dev, hw) < 0)
-               return -1;
+       if (eth_dev->dev_type == RTE_ETH_DEV_PCI)
+               if (vtpci_init(pci_dev, hw) < 0)
+                       return -1;

        /* Reset the device although not necessary at startup */
        vtpci_reset(hw);
@@ -1052,10 +1072,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);

@@ -1132,15 +1154,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;
@@ -1173,10 +1197,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");
@@ -1241,11 +1266,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;
 }
@@ -1439,3 +1466,167 @@ static struct rte_driver rte_virtio_driver = {
 };

 PMD_REGISTER_DRIVER(rte_virtio_driver);
+
+#ifdef RTE_VIRTIO_VDEV
+
+static const char *valid_args[] = {
+#define ETH_CVIO_ARG_RX_NUM            "rx"
+       ETH_CVIO_ARG_RX_NUM,
+#define ETH_CVIO_ARG_TX_NUM            "tx"
+       ETH_CVIO_ARG_TX_NUM,
+#define ETH_CVIO_ARG_CQ_NUM            "cq"
+       ETH_CVIO_ARG_CQ_NUM,
+#define ETH_CVIO_ARG_MAC               "mac"
+       ETH_CVIO_ARG_MAC,
+#define ETH_CVIO_ARG_PATH              "path"
+       ETH_CVIO_ARG_PATH,
+#define ETH_CVIO_ARG_QUEUE_SIZE                "queue_num"
+       ETH_CVIO_ARG_QUEUE_SIZE,
+#define ETH_CVIO_ARG_IFNAME            "ifname"
+       ETH_CVIO_ARG_IFNAME,
+       NULL
+};
+
+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;
+       eth_dev->pci_dev = NULL;
+       /* will be used in virtio_dev_info_get() */
+       eth_dev->driver = &rte_virtio_pmd;
+       /* TODO: eth_dev->link_intr_cbs */
+       return eth_dev;
+}
+
+#define CVIO_DEF_CQ_EN         0
+#define CVIO_DEF_Q_NUM         1
+#define CVIO_DEF_Q_SZ          256
+/* 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_num = 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",
+                         ETH_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, ETH_CVIO_ARG_PATH) == 1)
+               rte_kvargs_process(kvlist, ETH_CVIO_ARG_PATH,
+                                  &get_string_arg, &sock_path);
+       else
+               rte_panic("arg %s is mandatory for eth_cvio\n",
+                         ETH_CVIO_ARG_QUEUE_SIZE);
+
+       if (rte_kvargs_count(kvlist, ETH_CVIO_ARG_MAC) == 1)
+               rte_kvargs_process(kvlist, ETH_CVIO_ARG_MAC,
+                                  &get_string_arg, &mac_addr);
+
+       if (rte_kvargs_count(kvlist, ETH_CVIO_ARG_IFNAME) == 1)
+               rte_kvargs_process(kvlist, ETH_CVIO_ARG_IFNAME,
+                                  &get_string_arg, &ifname);
+
+       if (rte_kvargs_count(kvlist, ETH_CVIO_ARG_QUEUE_SIZE) == 1)
+               rte_kvargs_process(kvlist, ETH_CVIO_ARG_QUEUE_SIZE,
+                                  &get_integer_arg, &queue_num);
+
+       if (rte_kvargs_count(kvlist, ETH_CVIO_ARG_RX_NUM) == 1)
+               rte_kvargs_process(kvlist, ETH_CVIO_ARG_RX_NUM,
+                                  &get_integer_arg, &nb_rx);
+
+       if (rte_kvargs_count(kvlist, ETH_CVIO_ARG_TX_NUM) == 1)
+               rte_kvargs_process(kvlist, ETH_CVIO_ARG_TX_NUM,
+                                  &get_integer_arg, &nb_tx);
+
+       if (rte_kvargs_count(kvlist, ETH_CVIO_ARG_CQ_NUM) == 1)
+               rte_kvargs_process(kvlist, ETH_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_num, 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;
+}
+
+static int
+rte_cvio_pmd_devuninit(const char *name)
+{
+       rte_panic("%s", name);
+       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);
+
+#endif
diff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c
index 41a1366..cebd75a 100644
--- a/drivers/net/virtio/virtio_rxtx.c
+++ b/drivers/net/virtio/virtio_rxtx.c
@@ -191,8 +191,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);
+               RTE_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;
@@ -237,7 +236,8 @@ virtqueue_enqueue_xmit(struct virtqueue *txvq, struct 
rte_mbuf *cookie)

        for (; ((seg_num > 0) && (cookie != NULL)); seg_num--) {
                idx = start_dp[idx].next;
-               start_dp[idx].addr  = RTE_MBUF_DATA_DMA_ADDR(cookie);
+               start_dp[idx].addr  =
+                       RTE_MBUF_DATA_DMA_ADDR(cookie, txvq->offset);
                start_dp[idx].len   = cookie->data_len;
                start_dp[idx].flags = VRING_DESC_F_NEXT;
                cookie = cookie->next;
diff --git a/drivers/net/virtio/virtio_rxtx_simple.c 
b/drivers/net/virtio/virtio_rxtx_simple.c
index 3a1de9d..92a6388 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 = RTE_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);
+                       RTE_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);
+                               RTE_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 = RTE_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 99d4fa9..057c4ed 100644
--- a/drivers/net/virtio/virtqueue.h
+++ b/drivers/net/virtio/virtqueue.h
@@ -66,8 +66,14 @@ struct rte_mbuf;

 #define VIRTQUEUE_MAX_NAME_SZ 32

-#define RTE_MBUF_DATA_DMA_ADDR(mb) \
-       (uint64_t) ((mb)->buf_physaddr + (mb)->data_off)
+#ifdef RTE_VIRTIO_VDEV
+#define RTE_MBUF_DATA_DMA_ADDR(mb, offset) \
+       ((uint64_t)((uintptr_t)(*(void **)((uintptr_t)mb + offset)) \
+                       + (mb)->data_off))
+#else
+#define RTE_MBUF_DATA_DMA_ADDR(mb, offset) \
+       ((uint64_t)((mb)->buf_physaddr + (mb)->data_off))
+#endif /* RTE_VIRTIO_VDEV */

 #define VTNET_SQ_RQ_QUEUE_IDX 0
 #define VTNET_SQ_TQ_QUEUE_IDX 1
@@ -167,7 +173,8 @@ 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 */
+       phys_addr_t vq_ring_mem;          /**< phys addr of vring for pci dev */
+                                         /**< virt addr of vring for vdev. */

        struct vring vq_ring;    /**< vring keeping desc, used and avail */
        uint16_t    vq_free_cnt; /**< num of desc available */
@@ -186,8 +193,10 @@ 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 */
+       void        *virtio_net_hdr_vaddr;    /**< linear address of vring*/

        struct rte_mbuf **sw_ring; /**< RX software ring. */
        /* dummy mbuf, for wraparound when processing RX ring. */
-- 
2.1.4

Reply via email to