X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fvirtio%2Fvirtio_user_ethdev.c;h=90fcd6e7cc2652767b81ced2b56a656f5eba16db;hb=1c9e61b3a45321b3cae742e8769b10c06c0324f0;hp=150a8d9877f0bf28d0db32b317d60da3571af537;hpb=4710e16a4a7b53c9f2cf38e6f6af945e9af59c26;p=dpdk.git diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c index 150a8d9877..90fcd6e7cc 100644 --- a/drivers/net/virtio/virtio_user_ethdev.c +++ b/drivers/net/virtio/virtio_user_ethdev.c @@ -6,154 +6,27 @@ #include #include #include +#include +#include +#include #include #include #include -#include +#include #include #include #include #include "virtio_ethdev.h" #include "virtio_logs.h" -#include "virtio_pci.h" +#include "virtio.h" #include "virtqueue.h" #include "virtio_rxtx.h" #include "virtio_user/virtio_user_dev.h" #include "virtio_user/vhost.h" -#define virtio_user_get_dev(hw) \ - ((struct virtio_user_dev *)(hw)->virtio_user_dev) - -static void -virtio_user_reset_queues_packed(struct rte_eth_dev *dev) -{ - struct virtio_hw *hw = dev->data->dev_private; - struct virtnet_rx *rxvq; - struct virtnet_tx *txvq; - uint16_t i; - - /* Add lock to avoid queue contention. */ - rte_spinlock_lock(&hw->state_lock); - hw->started = 0; - - /* - * Waitting for datapath to complete before resetting queues. - * 1 ms should be enough for the ongoing Tx/Rx function to finish. - */ - rte_delay_ms(1); - - /* Vring reset for each Tx queue and Rx queue. */ - for (i = 0; i < dev->data->nb_rx_queues; i++) { - rxvq = dev->data->rx_queues[i]; - virtqueue_rxvq_reset_packed(rxvq->vq); - virtio_dev_rx_queue_setup_finish(dev, i); - } - - for (i = 0; i < dev->data->nb_tx_queues; i++) { - txvq = dev->data->tx_queues[i]; - virtqueue_txvq_reset_packed(txvq->vq); - } - - hw->started = 1; - rte_spinlock_unlock(&hw->state_lock); -} - - -static int -virtio_user_server_reconnect(struct virtio_user_dev *dev) -{ - int ret; - int connectfd; - struct rte_eth_dev *eth_dev = &rte_eth_devices[dev->port_id]; - struct virtio_hw *hw = eth_dev->data->dev_private; - - connectfd = accept(dev->listenfd, NULL, NULL); - if (connectfd < 0) - return -1; - - dev->vhostfd = connectfd; - if (dev->ops->send_request(dev, VHOST_USER_GET_FEATURES, - &dev->device_features) < 0) { - PMD_INIT_LOG(ERR, "get_features failed: %s", - strerror(errno)); - return -1; - } - - dev->device_features |= dev->frontend_features; - - /* umask vhost-user unsupported features */ - dev->device_features &= ~(dev->unsupported_features); - - dev->features &= dev->device_features; - - /* For packed ring, resetting queues is required in reconnection. */ - if (vtpci_packed_queue(hw)) { - PMD_INIT_LOG(NOTICE, "Packets on the fly will be dropped" - " when packed ring reconnecting."); - virtio_user_reset_queues_packed(eth_dev); - } - - ret = virtio_user_start_device(dev); - if (ret < 0) - return -1; - - if (dev->queue_pairs > 1) { - ret = virtio_user_handle_mq(dev, dev->queue_pairs); - if (ret != 0) { - PMD_INIT_LOG(ERR, "Fails to enable multi-queue pairs!"); - return -1; - } - } - if (eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC) { - if (rte_intr_disable(eth_dev->intr_handle) < 0) { - PMD_DRV_LOG(ERR, "interrupt disable failed"); - return -1; - } - rte_intr_callback_unregister(eth_dev->intr_handle, - virtio_interrupt_handler, - eth_dev); - eth_dev->intr_handle->fd = connectfd; - rte_intr_callback_register(eth_dev->intr_handle, - virtio_interrupt_handler, eth_dev); - - if (rte_intr_enable(eth_dev->intr_handle) < 0) { - PMD_DRV_LOG(ERR, "interrupt enable failed"); - return -1; - } - } - PMD_INIT_LOG(NOTICE, "server mode virtio-user reconnection succeeds!"); - return 0; -} - -static void -virtio_user_delayed_handler(void *param) -{ - struct virtio_hw *hw = (struct virtio_hw *)param; - struct rte_eth_dev *eth_dev = &rte_eth_devices[hw->port_id]; - struct virtio_user_dev *dev = virtio_user_get_dev(hw); - - if (rte_intr_disable(eth_dev->intr_handle) < 0) { - PMD_DRV_LOG(ERR, "interrupt disable failed"); - return; - } - rte_intr_callback_unregister(eth_dev->intr_handle, - virtio_interrupt_handler, eth_dev); - if (dev->is_server) { - if (dev->vhostfd >= 0) { - close(dev->vhostfd); - dev->vhostfd = -1; - } - eth_dev->intr_handle->fd = dev->listenfd; - rte_intr_callback_register(eth_dev->intr_handle, - virtio_interrupt_handler, eth_dev); - if (rte_intr_enable(eth_dev->intr_handle) < 0) { - PMD_DRV_LOG(ERR, "interrupt enable failed"); - return; - } - } -} +#define virtio_user_get_dev(hwp) container_of(hwp, struct virtio_user_dev, hw) static void virtio_user_read_dev_config(struct virtio_hw *hw, size_t offset, @@ -170,46 +43,9 @@ virtio_user_read_dev_config(struct virtio_hw *hw, size_t offset, } if (offset == offsetof(struct virtio_net_config, status)) { - char buf[128]; - - if (dev->vhostfd >= 0) { - int r; - int flags; - - flags = fcntl(dev->vhostfd, F_GETFL); - if (fcntl(dev->vhostfd, F_SETFL, - flags | O_NONBLOCK) == -1) { - PMD_DRV_LOG(ERR, "error setting O_NONBLOCK flag"); - return; - } - r = recv(dev->vhostfd, buf, 128, MSG_PEEK); - if (r == 0 || (r < 0 && errno != EAGAIN)) { - dev->status &= (~VIRTIO_NET_S_LINK_UP); - PMD_DRV_LOG(ERR, "virtio-user port %u is down", - hw->port_id); - - /* This function could be called in the process - * of interrupt handling, callback cannot be - * unregistered here, set an alarm to do it. - */ - rte_eal_alarm_set(1, - virtio_user_delayed_handler, - (void *)hw); - } else { - dev->status |= VIRTIO_NET_S_LINK_UP; - } - if (fcntl(dev->vhostfd, F_SETFL, - flags & ~O_NONBLOCK) == -1) { - PMD_DRV_LOG(ERR, "error clearing O_NONBLOCK flag"); - return; - } - } else if (dev->is_server) { - dev->status &= (~VIRTIO_NET_S_LINK_UP); - if (virtio_user_server_reconnect(dev) >= 0) - dev->status |= VIRTIO_NET_S_LINK_UP; - } + virtio_user_dev_update_link_state(dev); - *(uint16_t *)dst = dev->status; + *(uint16_t *)dst = dev->net_status; } if (offset == offsetof(struct virtio_net_config, max_virtqueue_pairs)) @@ -224,12 +60,15 @@ virtio_user_write_dev_config(struct virtio_hw *hw, size_t offset, struct virtio_user_dev *dev = virtio_user_get_dev(hw); if ((offset == offsetof(struct virtio_net_config, mac)) && - (length == RTE_ETHER_ADDR_LEN)) + (length == RTE_ETHER_ADDR_LEN)) { for (i = 0; i < RTE_ETHER_ADDR_LEN; ++i) dev->mac_addr[i] = ((const uint8_t *)src)[i]; - else + virtio_user_dev_set_mac(dev); + virtio_user_dev_get_mac(dev); + } else { PMD_DRV_LOG(ERR, "not supported offset=%zu, len=%d", offset, length); + } } static void @@ -245,12 +84,17 @@ static void virtio_user_set_status(struct virtio_hw *hw, uint8_t status) { struct virtio_user_dev *dev = virtio_user_get_dev(hw); + uint8_t old_status = dev->status; + if (status & VIRTIO_CONFIG_STATUS_FEATURES_OK && + ~old_status & VIRTIO_CONFIG_STATUS_FEATURES_OK) + virtio_user_dev_set_features(dev); if (status & VIRTIO_CONFIG_STATUS_DRIVER_OK) virtio_user_start_device(dev); else if (status == VIRTIO_CONFIG_STATUS_RESET) virtio_user_reset(hw); - dev->status = status; + + virtio_user_dev_set_status(dev, status); } static uint8_t @@ -258,6 +102,8 @@ virtio_user_get_status(struct virtio_hw *hw) { struct virtio_user_dev *dev = virtio_user_get_dev(hw); + virtio_user_dev_update_status(dev); + return dev->status; } @@ -267,7 +113,8 @@ virtio_user_get_features(struct virtio_hw *hw) struct virtio_user_dev *dev = virtio_user_get_dev(hw); /* unmask feature bits defined in vhost user protocol */ - return dev->device_features & VIRTIO_PMD_SUPPORTED_GUEST_FEATURES; + return (dev->device_features | dev->frontend_features) & + VIRTIO_PMD_SUPPORTED_GUEST_FEATURES; } static void @@ -275,7 +122,13 @@ virtio_user_set_features(struct virtio_hw *hw, uint64_t features) { struct virtio_user_dev *dev = virtio_user_get_dev(hw); - dev->features = features & dev->device_features; + dev->features = features & (dev->device_features | dev->frontend_features); +} + +static int +virtio_user_features_ok(struct virtio_hw *hw __rte_unused) +{ + return 0; } static uint8_t @@ -284,7 +137,7 @@ virtio_user_get_isr(struct virtio_hw *hw __rte_unused) /* rxq interrupts and config interrupt are separated in virtio-user, * here we only report config change. */ - return VIRTIO_PCI_ISR_CONFIG; + return VIRTIO_ISR_CONFIG; } static uint16_t @@ -333,7 +186,7 @@ virtio_user_setup_queue_packed(struct virtqueue *vq, sizeof(struct vring_packed_desc); used_addr = RTE_ALIGN_CEIL(avail_addr + sizeof(struct vring_packed_desc_event), - VIRTIO_PCI_VRING_ALIGN); + VIRTIO_VRING_ALIGN); vring->num = vq->vq_nentries; vring->desc = (void *)(uintptr_t)desc_addr; vring->driver = (void *)(uintptr_t)avail_addr; @@ -355,7 +208,7 @@ virtio_user_setup_queue_split(struct virtqueue *vq, struct virtio_user_dev *dev) avail_addr = desc_addr + vq->vq_nentries * sizeof(struct vring_desc); used_addr = RTE_ALIGN_CEIL(avail_addr + offsetof(struct vring_avail, ring[vq->vq_nentries]), - VIRTIO_PCI_VRING_ALIGN); + VIRTIO_VRING_ALIGN); dev->vrings[queue_idx].num = vq->vq_nentries; dev->vrings[queue_idx].desc = (void *)(uintptr_t)desc_addr; @@ -368,7 +221,7 @@ virtio_user_setup_queue(struct virtio_hw *hw, struct virtqueue *vq) { struct virtio_user_dev *dev = virtio_user_get_dev(hw); - if (vtpci_packed_queue(hw)) + if (virtio_with_packed_queue(hw)) virtio_user_setup_queue_packed(vq, dev); else virtio_user_setup_queue_split(vq, dev); @@ -400,8 +253,8 @@ virtio_user_notify_queue(struct virtio_hw *hw, struct virtqueue *vq) uint64_t buf = 1; struct virtio_user_dev *dev = virtio_user_get_dev(hw); - if (hw->cvq && (hw->cvq->vq == vq)) { - if (vtpci_packed_queue(vq->hw)) + if (hw->cvq && (virtnet_cq_to_vq(hw->cvq) == vq)) { + if (virtio_with_packed_queue(vq->hw)) virtio_user_handle_cq_packed(dev, vq->vq_queue_index); else virtio_user_handle_cq(dev, vq->vq_queue_index); @@ -413,13 +266,24 @@ virtio_user_notify_queue(struct virtio_hw *hw, struct virtqueue *vq) strerror(errno)); } -const struct virtio_pci_ops virtio_user_ops = { +static int +virtio_user_dev_close(struct virtio_hw *hw) +{ + struct virtio_user_dev *dev = virtio_user_get_dev(hw); + + virtio_user_dev_uninit(dev); + + return 0; +} + +const struct virtio_ops virtio_user_ops = { .read_dev_cfg = virtio_user_read_dev_config, .write_dev_cfg = virtio_user_write_dev_config, .get_status = virtio_user_get_status, .set_status = virtio_user_set_status, .get_features = virtio_user_get_features, .set_features = virtio_user_set_features, + .features_ok = virtio_user_features_ok, .get_isr = virtio_user_get_isr, .set_config_irq = virtio_user_set_config_irq, .set_queue_irq = virtio_user_set_queue_irq, @@ -427,6 +291,7 @@ const struct virtio_pci_ops virtio_user_ops = { .setup_queue = virtio_user_setup_queue, .del_queue = virtio_user_del_queue, .notify_queue = virtio_user_notify_queue, + .dev_close = virtio_user_dev_close, }; static const char *valid_args[] = { @@ -452,6 +317,8 @@ static const char *valid_args[] = { VIRTIO_USER_ARG_PACKED_VQ, #define VIRTIO_USER_ARG_SPEED "speed" VIRTIO_USER_ARG_SPEED, +#define VIRTIO_USER_ARG_VECTORIZED "vectorized" + VIRTIO_USER_ARG_VECTORIZED, NULL }; @@ -492,6 +359,61 @@ get_integer_arg(const char *key __rte_unused, return -errno; } +static uint32_t +vdpa_dynamic_major_num(void) +{ + FILE *fp; + char *line = NULL; + size_t size = 0; + char name[11]; + bool found = false; + uint32_t num; + + fp = fopen("/proc/devices", "r"); + if (fp == NULL) { + PMD_INIT_LOG(ERR, "Cannot open /proc/devices: %s", + strerror(errno)); + return UNNAMED_MAJOR; + } + + while (getline(&line, &size, fp) > 0) { + char *stripped = line + strspn(line, " "); + if ((sscanf(stripped, "%u %10s", &num, name) == 2) && + (strncmp(name, "vhost-vdpa", 10) == 0)) { + found = true; + break; + } + } + free(line); + fclose(fp); + return found ? num : UNNAMED_MAJOR; +} + +static enum virtio_user_backend_type +virtio_user_backend_type(const char *path) +{ + struct stat sb; + + if (stat(path, &sb) == -1) { + if (errno == ENOENT) + return VIRTIO_USER_BACKEND_VHOST_USER; + + PMD_INIT_LOG(ERR, "Stat fails: %s (%s)\n", path, + strerror(errno)); + return VIRTIO_USER_BACKEND_UNKNOWN; + } + + if (S_ISSOCK(sb.st_mode)) { + return VIRTIO_USER_BACKEND_VHOST_USER; + } else if (S_ISCHR(sb.st_mode)) { + if (major(sb.st_rdev) == MISC_MAJOR) + return VIRTIO_USER_BACKEND_VHOST_KERNEL; + if (major(sb.st_rdev) == vdpa_dynamic_major_num()) + return VIRTIO_USER_BACKEND_VHOST_VDPA; + } + return VIRTIO_USER_BACKEND_UNKNOWN; +} + static struct rte_eth_dev * virtio_user_eth_dev_alloc(struct rte_vdev_device *vdev) { @@ -500,45 +422,31 @@ virtio_user_eth_dev_alloc(struct rte_vdev_device *vdev) struct virtio_hw *hw; struct virtio_user_dev *dev; - eth_dev = rte_eth_vdev_allocate(vdev, sizeof(*hw)); + eth_dev = rte_eth_vdev_allocate(vdev, sizeof(*dev)); if (!eth_dev) { PMD_INIT_LOG(ERR, "cannot alloc rte_eth_dev"); return NULL; } data = eth_dev->data; - hw = eth_dev->data->dev_private; - - dev = rte_zmalloc(NULL, sizeof(*dev), 0); - if (!dev) { - PMD_INIT_LOG(ERR, "malloc virtio_user_dev failed"); - rte_eth_dev_release_port(eth_dev); - return NULL; - } + dev = eth_dev->data->dev_private; + hw = &dev->hw; hw->port_id = data->port_id; - dev->port_id = data->port_id; - virtio_hw_internal[hw->port_id].vtpci_ops = &virtio_user_ops; - /* - * MSIX is required to enable LSC (see virtio_init_device). - * Here just pretend that we support msix. - */ - hw->use_msix = 1; - hw->modern = 0; + VIRTIO_OPS(hw) = &virtio_user_ops; + + hw->intr_lsc = 1; hw->use_vec_rx = 0; + hw->use_vec_tx = 0; hw->use_inorder_rx = 0; hw->use_inorder_tx = 0; - hw->virtio_user_dev = dev; + return eth_dev; } static void virtio_user_eth_dev_free(struct rte_eth_dev *eth_dev) { - struct rte_eth_dev_data *data = eth_dev->data; - struct virtio_hw *hw = data->dev_private; - - rte_free(hw->virtio_user_dev); rte_eth_dev_release_port(eth_dev); } @@ -547,11 +455,13 @@ virtio_user_eth_dev_free(struct rte_eth_dev *eth_dev) * Returns 0 on success. */ static int -virtio_user_pmd_probe(struct rte_vdev_device *dev) +virtio_user_pmd_probe(struct rte_vdev_device *vdev) { struct rte_kvargs *kvlist = NULL; struct rte_eth_dev *eth_dev; struct virtio_hw *hw; + struct virtio_user_dev *dev; + enum virtio_user_backend_type backend_type = VIRTIO_USER_BACKEND_UNKNOWN; uint64_t queues = VIRTIO_USER_DEF_Q_NUM; uint64_t cq = VIRTIO_USER_DEF_CQ_EN; uint64_t queue_size = VIRTIO_USER_DEF_Q_SZ; @@ -559,19 +469,26 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev) uint64_t mrg_rxbuf = 1; uint64_t in_order = 1; uint64_t packed_vq = 0; + uint64_t vectorized = 0; char *path = NULL; char *ifname = NULL; char *mac_addr = NULL; int ret = -1; + RTE_BUILD_BUG_ON(offsetof(struct virtio_user_dev, hw) != 0); + if (rte_eal_process_type() == RTE_PROC_SECONDARY) { - const char *name = rte_vdev_device_name(dev); + const char *name = rte_vdev_device_name(vdev); eth_dev = rte_eth_dev_attach_secondary(name); if (!eth_dev) { PMD_INIT_LOG(ERR, "Failed to probe %s", name); return -1; } + dev = eth_dev->data->dev_private; + hw = &dev->hw; + VIRTIO_OPS(hw) = &virtio_user_ops; + if (eth_virtio_dev_init(eth_dev) < 0) { PMD_INIT_LOG(ERR, "eth_virtio_dev_init fails"); rte_eth_dev_release_port(eth_dev); @@ -579,12 +496,12 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev) } eth_dev->dev_ops = &virtio_user_secondary_eth_dev_ops; - eth_dev->device = &dev->device; + eth_dev->device = &vdev->device; rte_eth_dev_probing_finish(eth_dev); return 0; } - kvlist = rte_kvargs_parse(rte_vdev_device_args(dev), valid_args); + kvlist = rte_kvargs_parse(rte_vdev_device_args(vdev), valid_args); if (!kvlist) { PMD_INIT_LOG(ERR, "error when parsing param"); goto end; @@ -603,8 +520,18 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev) goto end; } + backend_type = virtio_user_backend_type(path); + if (backend_type == VIRTIO_USER_BACKEND_UNKNOWN) { + PMD_INIT_LOG(ERR, + "unable to determine backend type for path %s", + path); + goto end; + } + PMD_INIT_LOG(INFO, "Backend type detected: %s", + virtio_user_backend_strings[backend_type]); + if (rte_kvargs_count(kvlist, VIRTIO_USER_ARG_INTERFACE_NAME) == 1) { - if (is_vhost_user_by_type(path)) { + if (backend_type != VIRTIO_USER_BACKEND_VHOST_KERNEL) { PMD_INIT_LOG(ERR, "arg %s applies only to vhost-kernel backend", VIRTIO_USER_ARG_INTERFACE_NAME); @@ -675,6 +602,15 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev) } } + if (rte_kvargs_count(kvlist, VIRTIO_USER_ARG_VECTORIZED) == 1) { + if (rte_kvargs_process(kvlist, VIRTIO_USER_ARG_VECTORIZED, + &get_integer_arg, &vectorized) < 0) { + PMD_INIT_LOG(ERR, "error to parse %s", + VIRTIO_USER_ARG_VECTORIZED); + goto end; + } + } + if (queues > 1 && cq == 0) { PMD_INIT_LOG(ERR, "multi-q requires ctrl-q"); goto end; @@ -705,28 +641,43 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev) } } - eth_dev = virtio_user_eth_dev_alloc(dev); + eth_dev = virtio_user_eth_dev_alloc(vdev); if (!eth_dev) { PMD_INIT_LOG(ERR, "virtio_user fails to alloc device"); goto end; } - hw = eth_dev->data->dev_private; - if (virtio_user_dev_init(hw->virtio_user_dev, path, queues, cq, + dev = eth_dev->data->dev_private; + hw = &dev->hw; + if (virtio_user_dev_init(dev, path, queues, cq, queue_size, mac_addr, &ifname, server_mode, - mrg_rxbuf, in_order, packed_vq) < 0) { + mrg_rxbuf, in_order, packed_vq, backend_type) < 0) { PMD_INIT_LOG(ERR, "virtio_user_dev_init fails"); virtio_user_eth_dev_free(eth_dev); goto end; } - /* previously called by rte_pci_probe() for physical dev */ + /* previously called by pci probing for physical dev */ if (eth_virtio_dev_init(eth_dev) < 0) { PMD_INIT_LOG(ERR, "eth_virtio_dev_init fails"); virtio_user_eth_dev_free(eth_dev); goto end; } + if (vectorized) { + if (packed_vq) { +#if defined(CC_AVX512_SUPPORT) || defined(RTE_ARCH_ARM) + hw->use_vec_rx = 1; + hw->use_vec_tx = 1; +#else + PMD_INIT_LOG(INFO, + "building environment do not support packed ring vectorized"); +#endif + } else { + hw->use_vec_rx = 1; + } + } + rte_eth_dev_probing_finish(eth_dev); ret = 0; @@ -762,7 +713,53 @@ virtio_user_pmd_remove(struct rte_vdev_device *vdev) return rte_eth_dev_release_port(eth_dev); /* make sure the device is stopped, queues freed */ - rte_eth_dev_close(eth_dev->data->port_id); + return rte_eth_dev_close(eth_dev->data->port_id); +} + +static int virtio_user_pmd_dma_map(struct rte_vdev_device *vdev, void *addr, + uint64_t iova, size_t len) +{ + const char *name; + struct rte_eth_dev *eth_dev; + struct virtio_user_dev *dev; + + if (!vdev) + return -EINVAL; + + name = rte_vdev_device_name(vdev); + eth_dev = rte_eth_dev_allocated(name); + /* Port has already been released by close. */ + if (!eth_dev) + return 0; + + dev = eth_dev->data->dev_private; + + if (dev->ops->dma_map) + return dev->ops->dma_map(dev, addr, iova, len); + + return 0; +} + +static int virtio_user_pmd_dma_unmap(struct rte_vdev_device *vdev, void *addr, + uint64_t iova, size_t len) +{ + const char *name; + struct rte_eth_dev *eth_dev; + struct virtio_user_dev *dev; + + if (!vdev) + return -EINVAL; + + name = rte_vdev_device_name(vdev); + eth_dev = rte_eth_dev_allocated(name); + /* Port has already been released by close. */ + if (!eth_dev) + return 0; + + dev = eth_dev->data->dev_private; + + if (dev->ops->dma_unmap) + return dev->ops->dma_unmap(dev, addr, iova, len); return 0; } @@ -770,6 +767,9 @@ virtio_user_pmd_remove(struct rte_vdev_device *vdev) static struct rte_vdev_driver virtio_user_driver = { .probe = virtio_user_pmd_probe, .remove = virtio_user_pmd_remove, + .dma_map = virtio_user_pmd_dma_map, + .dma_unmap = virtio_user_pmd_dma_unmap, + .drv_flags = RTE_VDEV_DRV_NEED_IOVA_AS_VA, }; RTE_PMD_REGISTER_VDEV(net_virtio_user, virtio_user_driver); @@ -785,4 +785,5 @@ RTE_PMD_REGISTER_PARAM_STRING(net_virtio_user, "mrg_rxbuf=<0|1> " "in_order=<0|1> " "packed_vq=<0|1> " - "speed="); + "speed= " + "vectorized=<0|1>");