X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fvirtio%2Fvirtio_user%2Fvhost_kernel.c;h=69f932bede0c925803e258558c96649558623893;hb=539d910c9c76876dfcfefea632dd32c603d76672;hp=b79dcad17949f1a2751e1200e3abe2fb31163f6c;hpb=06856cabb89b0db000a065c17e32cdf2d2f58470;p=dpdk.git diff --git a/drivers/net/virtio/virtio_user/vhost_kernel.c b/drivers/net/virtio/virtio_user/vhost_kernel.c index b79dcad179..69f932bede 100644 --- a/drivers/net/virtio/virtio_user/vhost_kernel.c +++ b/drivers/net/virtio/virtio_user/vhost_kernel.c @@ -38,6 +38,28 @@ struct vhost_memory_kernel { #define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file) #define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file) +/* with below features, vhost kernel does not need to do the checksum and TSO, + * these info will be passed to virtio_user through virtio net header. + */ +#define VHOST_KERNEL_GUEST_OFFLOADS_MASK \ + ((1ULL << VIRTIO_NET_F_GUEST_CSUM) | \ + (1ULL << VIRTIO_NET_F_GUEST_TSO4) | \ + (1ULL << VIRTIO_NET_F_GUEST_TSO6) | \ + (1ULL << VIRTIO_NET_F_GUEST_ECN) | \ + (1ULL << VIRTIO_NET_F_GUEST_UFO)) + +/* with below features, when flows from virtio_user to vhost kernel + * (1) if flows goes up through the kernel networking stack, it does not need + * to verify checksum, which can save CPU cycles; + * (2) if flows goes through a Linux bridge and outside from an interface + * (kernel driver), checksum and TSO will be done by GSO in kernel or even + * offloaded into real physical device. + */ +#define VHOST_KERNEL_HOST_OFFLOADS_MASK \ + ((1ULL << VIRTIO_NET_F_HOST_TSO4) | \ + (1ULL << VIRTIO_NET_F_HOST_TSO6) | \ + (1ULL << VIRTIO_NET_F_CSUM)) + static uint64_t max_regions = 64; static void @@ -77,18 +99,54 @@ vhost_kernel_set_owner(struct virtio_user_dev *dev) return vhost_kernel_ioctl(dev->vhostfds[0], VHOST_SET_OWNER, NULL); } -static uint64_t vhost_req_user_to_kernel[] = { - [VHOST_USER_RESET_OWNER] = VHOST_RESET_OWNER, - [VHOST_USER_SET_FEATURES] = VHOST_SET_FEATURES, - [VHOST_USER_GET_FEATURES] = VHOST_GET_FEATURES, - [VHOST_USER_SET_VRING_CALL] = VHOST_SET_VRING_CALL, - [VHOST_USER_SET_VRING_NUM] = VHOST_SET_VRING_NUM, - [VHOST_USER_SET_VRING_BASE] = VHOST_SET_VRING_BASE, - [VHOST_USER_GET_VRING_BASE] = VHOST_GET_VRING_BASE, - [VHOST_USER_SET_VRING_ADDR] = VHOST_SET_VRING_ADDR, - [VHOST_USER_SET_VRING_KICK] = VHOST_SET_VRING_KICK, - [VHOST_USER_SET_MEM_TABLE] = VHOST_SET_MEM_TABLE, -}; +static int +vhost_kernel_get_features(struct virtio_user_dev *dev, uint64_t *features) +{ + int ret; + unsigned int tap_features; + + ret = vhost_kernel_ioctl(dev->vhostfds[0], VHOST_GET_FEATURES, features); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Failed to get features"); + return -1; + } + + ret = tap_support_features(&tap_features); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Failed to get TAP features"); + return -1; + } + + /* with tap as the backend, all these features are supported + * but not claimed by vhost-net, so we add them back when + * reporting to upper layer. + */ + if (tap_features & IFF_VNET_HDR) { + *features |= VHOST_KERNEL_GUEST_OFFLOADS_MASK; + *features |= VHOST_KERNEL_HOST_OFFLOADS_MASK; + } + + /* vhost_kernel will not declare this feature, but it does + * support multi-queue. + */ + if (tap_features & IFF_MULTI_QUEUE) + *features |= (1ull << VIRTIO_NET_F_MQ); + + return 0; +} + +static int +vhost_kernel_set_features(struct virtio_user_dev *dev, uint64_t features) +{ + /* We don't need memory protection here */ + features &= ~(1ULL << VIRTIO_F_IOMMU_PLATFORM); + /* VHOST kernel does not know about below flags */ + features &= ~VHOST_KERNEL_GUEST_OFFLOADS_MASK; + features &= ~VHOST_KERNEL_HOST_OFFLOADS_MASK; + features &= ~(1ULL << VIRTIO_NET_F_MQ); + + return vhost_kernel_ioctl(dev->vhostfds[0], VHOST_SET_FEATURES, &features); +} static int add_memseg_list(const struct rte_memseg_list *msl, void *arg) @@ -124,16 +182,17 @@ add_memseg_list(const struct rte_memseg_list *msl, void *arg) * have much more memory regions. Below function will treat each * contiguous memory space reserved by DPDK as one region. */ -static struct vhost_memory_kernel * -prepare_vhost_memory_kernel(void) +static int +vhost_kernel_set_memory_table(struct virtio_user_dev *dev) { struct vhost_memory_kernel *vm; + int ret; vm = malloc(sizeof(struct vhost_memory_kernel) + max_regions * sizeof(struct vhost_memory_region)); if (!vm) - return NULL; + goto err; vm->nregions = 0; vm->padding = 0; @@ -142,59 +201,34 @@ prepare_vhost_memory_kernel(void) * The memory lock has already been taken by memory subsystem * or virtio_user_start_device(). */ - if (rte_memseg_list_walk_thread_unsafe(add_memseg_list, vm) < 0) { - free(vm); - return NULL; - } - - return vm; -} - -/* with below features, vhost kernel does not need to do the checksum and TSO, - * these info will be passed to virtio_user through virtio net header. - */ -#define VHOST_KERNEL_GUEST_OFFLOADS_MASK \ - ((1ULL << VIRTIO_NET_F_GUEST_CSUM) | \ - (1ULL << VIRTIO_NET_F_GUEST_TSO4) | \ - (1ULL << VIRTIO_NET_F_GUEST_TSO6) | \ - (1ULL << VIRTIO_NET_F_GUEST_ECN) | \ - (1ULL << VIRTIO_NET_F_GUEST_UFO)) - -/* with below features, when flows from virtio_user to vhost kernel - * (1) if flows goes up through the kernel networking stack, it does not need - * to verify checksum, which can save CPU cycles; - * (2) if flows goes through a Linux bridge and outside from an interface - * (kernel driver), checksum and TSO will be done by GSO in kernel or even - * offloaded into real physical device. - */ -#define VHOST_KERNEL_HOST_OFFLOADS_MASK \ - ((1ULL << VIRTIO_NET_F_HOST_TSO4) | \ - (1ULL << VIRTIO_NET_F_HOST_TSO6) | \ - (1ULL << VIRTIO_NET_F_CSUM)) - -static unsigned int -tap_support_features(void) -{ - int tapfd; - unsigned int tap_features; + ret = rte_memseg_list_walk_thread_unsafe(add_memseg_list, vm); + if (ret < 0) + goto err_free; - tapfd = open(PATH_NET_TUN, O_RDWR); - if (tapfd < 0) { - PMD_DRV_LOG(ERR, "fail to open %s: %s", - PATH_NET_TUN, strerror(errno)); - return -1; - } + ret = vhost_kernel_ioctl(dev->vhostfds[0], VHOST_SET_MEM_TABLE, vm); + if (ret < 0) + goto err_free; - if (ioctl(tapfd, TUNGETFEATURES, &tap_features) == -1) { - PMD_DRV_LOG(ERR, "TUNGETFEATURES failed: %s", strerror(errno)); - close(tapfd); - return -1; - } + free(vm); - close(tapfd); - return tap_features; + return 0; +err_free: + free(vm); +err: + PMD_DRV_LOG(ERR, "Failed to set memory table"); + return -1; } +static uint64_t vhost_req_user_to_kernel[] = { + [VHOST_USER_RESET_OWNER] = VHOST_RESET_OWNER, + [VHOST_USER_SET_VRING_CALL] = VHOST_SET_VRING_CALL, + [VHOST_USER_SET_VRING_NUM] = VHOST_SET_VRING_NUM, + [VHOST_USER_SET_VRING_BASE] = VHOST_SET_VRING_BASE, + [VHOST_USER_GET_VRING_BASE] = VHOST_GET_VRING_BASE, + [VHOST_USER_SET_VRING_ADDR] = VHOST_SET_VRING_ADDR, + [VHOST_USER_SET_VRING_KICK] = VHOST_SET_VRING_KICK, +}; + static int vhost_kernel_send_request(struct virtio_user_dev *dev, enum vhost_user_request req, @@ -203,33 +237,13 @@ vhost_kernel_send_request(struct virtio_user_dev *dev, int ret = -1; unsigned int i; uint64_t req_kernel; - struct vhost_memory_kernel *vm = NULL; int vhostfd; unsigned int queue_sel; - unsigned int features; PMD_DRV_LOG(INFO, "%s", vhost_msg_strings[req]); req_kernel = vhost_req_user_to_kernel[req]; - if (req_kernel == VHOST_SET_MEM_TABLE) { - vm = prepare_vhost_memory_kernel(); - if (!vm) - return -1; - arg = (void *)vm; - } - - if (req_kernel == VHOST_SET_FEATURES) { - /* We don't need memory protection here */ - *(uint64_t *)arg &= ~(1ULL << VIRTIO_F_IOMMU_PLATFORM); - - /* VHOST kernel does not know about below flags */ - *(uint64_t *)arg &= ~VHOST_KERNEL_GUEST_OFFLOADS_MASK; - *(uint64_t *)arg &= ~VHOST_KERNEL_HOST_OFFLOADS_MASK; - - *(uint64_t *)arg &= ~(1ULL << VIRTIO_NET_F_MQ); - } - switch (req_kernel) { case VHOST_SET_VRING_NUM: case VHOST_SET_VRING_ADDR: @@ -259,27 +273,6 @@ vhost_kernel_send_request(struct virtio_user_dev *dev, ret = ioctl(vhostfd, req_kernel, arg); } - if (!ret && req_kernel == VHOST_GET_FEATURES) { - features = tap_support_features(); - /* with tap as the backend, all these features are supported - * but not claimed by vhost-net, so we add them back when - * reporting to upper layer. - */ - if (features & IFF_VNET_HDR) { - *((uint64_t *)arg) |= VHOST_KERNEL_GUEST_OFFLOADS_MASK; - *((uint64_t *)arg) |= VHOST_KERNEL_HOST_OFFLOADS_MASK; - } - - /* vhost_kernel will not declare this feature, but it does - * support multi-queue. - */ - if (features & IFF_MULTI_QUEUE) - *(uint64_t *)arg |= (1ull << VIRTIO_NET_F_MQ); - } - - if (vm) - free(vm); - if (ret < 0) PMD_DRV_LOG(ERR, "%s failed: %s", vhost_msg_strings[req], strerror(errno)); @@ -407,6 +400,9 @@ set_backend: struct virtio_user_backend_ops virtio_ops_kernel = { .setup = vhost_kernel_setup, .set_owner = vhost_kernel_set_owner, + .get_features = vhost_kernel_get_features, + .set_features = vhost_kernel_set_features, + .set_memory_table = vhost_kernel_set_memory_table, .send_request = vhost_kernel_send_request, .enable_qp = vhost_kernel_enable_queue_pair };