#define virtio_user_get_dev(hwp) container_of(hwp, struct virtio_user_dev, hw)
-static void
-virtio_user_reset_queues_packed(struct rte_eth_dev *eth_dev)
-{
- struct virtio_user_dev *dev = eth_dev->data->dev_private;
- struct virtio_hw *hw = &dev->hw;
- 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 < eth_dev->data->nb_rx_queues; i++) {
- rxvq = eth_dev->data->rx_queues[i];
- virtqueue_rxvq_reset_packed(rxvq->vq);
- virtio_dev_rx_queue_setup_finish(eth_dev, i);
- }
-
- for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
- txvq = eth_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, connectfd, old_status;
- struct rte_eth_dev *eth_dev = &rte_eth_devices[dev->port_id];
- struct virtio_hw *hw = &dev->hw;
-
- connectfd = accept(dev->listenfd, NULL, NULL);
- if (connectfd < 0)
- return -1;
-
- dev->vhostfd = connectfd;
- old_status = dev->status;
-
- virtio_reset(hw);
-
- virtio_set_status(hw, VIRTIO_CONFIG_STATUS_ACK);
-
- virtio_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER);
-
- if (dev->ops->get_features(dev, &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 (virtio_with_packed_queue(hw) &&
- (old_status & VIRTIO_CONFIG_STATUS_DRIVER_OK)) {
- PMD_INIT_LOG(NOTICE, "Packets on the fly will be dropped"
- " when packed ring reconnecting.");
- virtio_user_reset_queues_packed(eth_dev);
- }
-
- virtio_set_status(hw, VIRTIO_CONFIG_STATUS_FEATURES_OK);
-
- /* Start the device */
- virtio_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER_OK);
- if (!dev->started)
- 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;
- }
- }
-}
-
static void
virtio_user_read_dev_config(struct virtio_hw *hw, size_t offset,
void *dst, int length)
}
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->net_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->net_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->net_status &= (~VIRTIO_NET_S_LINK_UP);
- if (virtio_user_server_reconnect(dev) >= 0)
- dev->net_status |= VIRTIO_NET_S_LINK_UP;
- }
+ virtio_user_dev_update_link_state(dev);
*(uint16_t *)dst = dev->net_status;
}
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
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
{
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
uint64_t buf = 1;
struct virtio_user_dev *dev = virtio_user_get_dev(hw);
- if (hw->cvq && (hw->cvq->vq == vq)) {
+ 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
{
FILE *fp;
char *line = NULL;
- size_t size;
+ size_t size = 0;
char name[11];
bool found = false;
uint32_t num;
break;
}
}
+ free(line);
fclose(fp);
return found ? num : UNNAMED_MAJOR;
}
if (errno == ENOENT)
return VIRTIO_USER_BACKEND_VHOST_USER;
- PMD_INIT_LOG(ERR, "Stat fails: %s (%s)\n", path,
+ PMD_INIT_LOG(ERR, "Stat fails: %s (%s)", path,
strerror(errno));
return VIRTIO_USER_BACKEND_UNKNOWN;
}
hw = &dev->hw;
hw->port_id = data->port_id;
- dev->port_id = data->port_id;
VIRTIO_OPS(hw) = &virtio_user_ops;
hw->intr_lsc = 1;
goto end;
}
+ /*
+ * Virtio-user requires using virtual addresses for the descriptors
+ * buffers, whatever other devices require
+ */
+ hw->use_va = true;
+
/* 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_dev_uninit(dev);
virtio_user_eth_dev_free(eth_dev);
goto end;
}
ret = 0;
end:
- if (kvlist)
- rte_kvargs_free(kvlist);
- if (path)
- free(path);
- if (mac_addr)
- free(mac_addr);
- if (ifname)
- free(ifname);
+ rte_kvargs_free(kvlist);
+ free(path);
+ free(mac_addr);
+ free(ifname);
return ret;
}
.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);