X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fvirtio%2Fvirtio_user%2Fvhost_kernel.c;h=202a8cdee1ca91a42659af628dcfd40b812c1acb;hb=1dfb92a529722c87b251eaaf673c48b13d1a54cc;hp=ad46f10a93000392ab933f4da4d80915c5bcaa69;hpb=b01e1e9a0d3e77e91dba61d90bed4ef6252e5ae0;p=dpdk.git diff --git a/drivers/net/virtio/virtio_user/vhost_kernel.c b/drivers/net/virtio/virtio_user/vhost_kernel.c index ad46f10a93..202a8cdee1 100644 --- a/drivers/net/virtio/virtio_user/vhost_kernel.c +++ b/drivers/net/virtio/virtio_user/vhost_kernel.c @@ -120,9 +120,9 @@ vhost_kernel_set_owner(struct virtio_user_dev *dev) static int vhost_kernel_get_features(struct virtio_user_dev *dev, uint64_t *features) { - int ret; - unsigned int tap_features; struct vhost_kernel_data *data = dev->backend_data; + unsigned int tap_flags; + int ret; ret = vhost_kernel_ioctl(data->vhostfds[0], VHOST_GET_FEATURES, features); if (ret < 0) { @@ -130,7 +130,7 @@ vhost_kernel_get_features(struct virtio_user_dev *dev, uint64_t *features) return -1; } - ret = tap_support_features(&tap_features); + ret = tap_get_flags(data->tapfds[0], &tap_flags); if (ret < 0) { PMD_DRV_LOG(ERR, "Failed to get TAP features"); return -1; @@ -140,7 +140,7 @@ vhost_kernel_get_features(struct virtio_user_dev *dev, uint64_t *features) * but not claimed by vhost-net, so we add them back when * reporting to upper layer. */ - if (tap_features & IFF_VNET_HDR) { + if (tap_flags & IFF_VNET_HDR) { *features |= VHOST_KERNEL_GUEST_OFFLOADS_MASK; *features |= VHOST_KERNEL_HOST_OFFLOADS_MASK; } @@ -148,7 +148,7 @@ vhost_kernel_get_features(struct virtio_user_dev *dev, uint64_t *features) /* vhost_kernel will not declare this feature, but it does * support multi-queue. */ - if (tap_features & IFF_MULTI_QUEUE) + if (tap_flags & IFF_MULTI_QUEUE) *features |= (1ull << VIRTIO_NET_F_MQ); return 0; @@ -158,6 +158,8 @@ static int vhost_kernel_set_features(struct virtio_user_dev *dev, uint64_t features) { struct vhost_kernel_data *data = dev->backend_data; + uint32_t i; + int ret; /* We don't need memory protection here */ features &= ~(1ULL << VIRTIO_F_IOMMU_PLATFORM); @@ -166,7 +168,16 @@ vhost_kernel_set_features(struct virtio_user_dev *dev, uint64_t features) features &= ~VHOST_KERNEL_HOST_OFFLOADS_MASK; features &= ~(1ULL << VIRTIO_NET_F_MQ); - return vhost_kernel_ioctl(data->vhostfds[0], VHOST_SET_FEATURES, &features); + for (i = 0; i < dev->max_queue_pairs; ++i) { + if (data->vhostfds[i] < 0) + continue; + + ret = vhost_kernel_ioctl(data->vhostfds[i], VHOST_SET_FEATURES, &features); + if (ret < 0) + return ret; + } + + return 0; } static int @@ -369,9 +380,20 @@ vhost_kernel_set_status(struct virtio_user_dev *dev __rte_unused, uint8_t status static int vhost_kernel_setup(struct virtio_user_dev *dev) { - int vhostfd; - uint32_t q, i; struct vhost_kernel_data *data; + unsigned int tap_features; + unsigned int tap_flags; + const char *ifname; + uint32_t q, i; + int vhostfd; + + if (tap_support_features(&tap_features) < 0) + return -1; + + if ((tap_features & IFF_VNET_HDR) == 0) { + PMD_INIT_LOG(ERR, "TAP does not support IFF_VNET_HDR"); + return -1; + } data = malloc(sizeof(*data)); if (!data) { @@ -403,18 +425,43 @@ vhost_kernel_setup(struct virtio_user_dev *dev) PMD_DRV_LOG(ERR, "fail to open %s, %s", dev->path, strerror(errno)); goto err_tapfds; } - data->vhostfds[i] = vhostfd; } + ifname = dev->ifname != NULL ? dev->ifname : "tap%d"; + data->tapfds[0] = tap_open(ifname, (tap_features & IFF_MULTI_QUEUE) != 0); + if (data->tapfds[0] < 0) + goto err_tapfds; + if (dev->ifname == NULL && tap_get_name(data->tapfds[0], &dev->ifname) < 0) { + PMD_DRV_LOG(ERR, "fail to get tap name (%d)", data->tapfds[0]); + goto err_tapfds; + } + if (tap_get_flags(data->tapfds[0], &tap_flags) < 0) { + PMD_DRV_LOG(ERR, "fail to get tap flags for tap %s", dev->ifname); + goto err_tapfds; + } + if ((tap_flags & IFF_MULTI_QUEUE) == 0 && dev->max_queue_pairs > 1) { + PMD_DRV_LOG(ERR, "tap %s does not support multi queue", dev->ifname); + goto err_tapfds; + } + + for (i = 1; i < dev->max_queue_pairs; i++) { + data->tapfds[i] = tap_open(dev->ifname, true); + if (data->tapfds[i] < 0) + goto err_tapfds; + } + dev->backend_data = data; return 0; err_tapfds: - for (i = 0; i < dev->max_queue_pairs; i++) + for (i = 0; i < dev->max_queue_pairs; i++) { if (data->vhostfds[i] >= 0) close(data->vhostfds[i]); + if (data->tapfds[i] >= 0) + close(data->tapfds[i]); + } free(data->tapfds); err_vhostfds: @@ -477,58 +524,42 @@ vhost_kernel_enable_queue_pair(struct virtio_user_dev *dev, uint16_t pair_idx, int enable) { + struct vhost_kernel_data *data = dev->backend_data; int hdr_size; int vhostfd; int tapfd; - int req_mq = (dev->max_queue_pairs > 1); - struct vhost_kernel_data *data = dev->backend_data; - - vhostfd = data->vhostfds[pair_idx]; if (dev->qp_enabled[pair_idx] == enable) return 0; + vhostfd = data->vhostfds[pair_idx]; + tapfd = data->tapfds[pair_idx]; + if (!enable) { - tapfd = data->tapfds[pair_idx]; if (vhost_kernel_set_backend(vhostfd, -1) < 0) { PMD_DRV_LOG(ERR, "fail to set backend for vhost kernel"); return -1; } - if (req_mq && vhost_kernel_tap_set_queue(tapfd, false) < 0) { - PMD_DRV_LOG(ERR, "fail to disable tap for vhost kernel"); - return -1; - } dev->qp_enabled[pair_idx] = false; return 0; } - if (data->tapfds[pair_idx] >= 0) { - tapfd = data->tapfds[pair_idx]; - if (vhost_kernel_tap_set_offload(tapfd, dev->features) == -1) - return -1; - if (req_mq && vhost_kernel_tap_set_queue(tapfd, true) < 0) { - PMD_DRV_LOG(ERR, "fail to enable tap for vhost kernel"); - return -1; - } - goto set_backend; - } - if ((dev->features & (1ULL << VIRTIO_NET_F_MRG_RXBUF)) || (dev->features & (1ULL << VIRTIO_F_VERSION_1))) hdr_size = sizeof(struct virtio_net_hdr_mrg_rxbuf); else hdr_size = sizeof(struct virtio_net_hdr); - tapfd = vhost_kernel_open_tap(&dev->ifname, hdr_size, req_mq, - (char *)dev->mac_addr, dev->features); - if (tapfd < 0) { - PMD_DRV_LOG(ERR, "fail to open tap for vhost kernel"); + /* Set mac on tap only once when starting */ + if (!dev->started && pair_idx == 0 && + tap_set_mac(data->tapfds[pair_idx], dev->mac_addr) < 0) return -1; - } - data->tapfds[pair_idx] = tapfd; + if (vhost_kernel_tap_setup(tapfd, hdr_size, dev->features) < 0) { + PMD_DRV_LOG(ERR, "fail to setup tap for vhost kernel"); + return -1; + } -set_backend: if (vhost_kernel_set_backend(vhostfd, tapfd) < 0) { PMD_DRV_LOG(ERR, "fail to set backend for vhost kernel"); return -1;