X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fvirtio%2Fvirtio_user%2Fvhost_kernel.c;h=58e66bb7b4ae01cde92a07215051ea9f0fb92c72;hb=55c1238246d53d196420fd2768dd3d4210ab654b;hp=f6e7cf47177bedffe790200861e41395ed876b5c;hpb=ab9098d20e377a37f4fb57945b83455f5b149e5e;p=dpdk.git diff --git a/drivers/net/virtio/virtio_user/vhost_kernel.c b/drivers/net/virtio/virtio_user/vhost_kernel.c index f6e7cf4717..58e66bb7b4 100644 --- a/drivers/net/virtio/virtio_user/vhost_kernel.c +++ b/drivers/net/virtio/virtio_user/vhost_kernel.c @@ -14,6 +14,11 @@ #include "virtio_user_dev.h" #include "vhost_kernel_tap.h" +struct vhost_kernel_data { + int *vhostfds; + int *tapfds; +}; + struct vhost_memory_kernel { uint32_t nregions; uint32_t padding; @@ -96,7 +101,20 @@ vhost_kernel_ioctl(int fd, uint64_t request, void *arg) static int vhost_kernel_set_owner(struct virtio_user_dev *dev) { - return vhost_kernel_ioctl(dev->vhostfds[0], VHOST_SET_OWNER, NULL); + int ret; + uint32_t i; + struct vhost_kernel_data *data = dev->backend_data; + + for (i = 0; i < dev->max_queue_pairs; ++i) { + if (data->vhostfds[i] < 0) + continue; + + ret = vhost_kernel_ioctl(data->vhostfds[i], VHOST_SET_OWNER, NULL); + if (ret < 0) + return ret; + } + + return 0; } static int @@ -104,8 +122,9 @@ 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; - ret = vhost_kernel_ioctl(dev->vhostfds[0], VHOST_GET_FEATURES, features); + ret = vhost_kernel_ioctl(data->vhostfds[0], VHOST_GET_FEATURES, features); if (ret < 0) { PMD_DRV_LOG(ERR, "Failed to get features"); return -1; @@ -138,6 +157,8 @@ vhost_kernel_get_features(struct virtio_user_dev *dev, uint64_t *features) static int vhost_kernel_set_features(struct virtio_user_dev *dev, uint64_t features) { + struct vhost_kernel_data *data = dev->backend_data; + /* We don't need memory protection here */ features &= ~(1ULL << VIRTIO_F_IOMMU_PLATFORM); /* VHOST kernel does not know about below flags */ @@ -145,7 +166,7 @@ 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(dev->vhostfds[0], VHOST_SET_FEATURES, &features); + return vhost_kernel_ioctl(data->vhostfds[0], VHOST_SET_FEATURES, &features); } static int @@ -185,6 +206,7 @@ add_memseg_list(const struct rte_memseg_list *msl, void *arg) static int vhost_kernel_set_memory_table(struct virtio_user_dev *dev) { + struct vhost_kernel_data *data = dev->backend_data; struct vhost_memory_kernel *vm; int ret; @@ -205,7 +227,7 @@ vhost_kernel_set_memory_table(struct virtio_user_dev *dev) if (ret < 0) goto err_free; - ret = vhost_kernel_ioctl(dev->vhostfds[0], VHOST_SET_MEM_TABLE, vm); + ret = vhost_kernel_ioctl(data->vhostfds[0], VHOST_SET_MEM_TABLE, vm); if (ret < 0) goto err_free; @@ -224,9 +246,10 @@ vhost_kernel_set_vring(struct virtio_user_dev *dev, uint64_t req, struct vhost_v { int ret, fd; unsigned int index = state->index; + struct vhost_kernel_data *data = dev->backend_data; /* Convert from queue index to queue-pair & offset */ - fd = dev->vhostfds[state->index / 2]; + fd = data->vhostfds[state->index / 2]; state->index %= 2; ret = vhost_kernel_ioctl(fd, req, state); @@ -259,59 +282,75 @@ vhost_kernel_get_vring_base(struct virtio_user_dev *dev, struct vhost_vring_stat return vhost_kernel_set_vring(dev, VHOST_GET_VRING_BASE, state); } -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_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, - void *arg) +vhost_kernel_set_vring_file(struct virtio_user_dev *dev, uint64_t req, + struct vhost_vring_file *file) { - int ret = -1; - unsigned int i; - uint64_t req_kernel; - int vhostfd; - unsigned int queue_sel; - - PMD_DRV_LOG(INFO, "%s", vhost_msg_strings[req]); - - req_kernel = vhost_req_user_to_kernel[req]; - - switch (req_kernel) { - case VHOST_SET_VRING_ADDR: - case VHOST_SET_VRING_KICK: - case VHOST_SET_VRING_CALL: - queue_sel = *(unsigned int *)arg; - vhostfd = dev->vhostfds[queue_sel / 2]; - *(unsigned int *)arg = queue_sel % 2; - PMD_DRV_LOG(DEBUG, "vhostfd=%d, index=%u", - vhostfd, *(unsigned int *)arg); - break; - default: - vhostfd = -1; + int ret, fd; + unsigned int index = file->index; + struct vhost_kernel_data *data = dev->backend_data; + + /* Convert from queue index to queue-pair & offset */ + fd = data->vhostfds[file->index / 2]; + file->index %= 2; + + ret = vhost_kernel_ioctl(fd, req, file); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Failed to set vring file (request %" PRIu64 ")", req); + return -1; } - if (vhostfd == -1) { - for (i = 0; i < dev->max_queue_pairs; ++i) { - if (dev->vhostfds[i] < 0) - continue; - - ret = ioctl(dev->vhostfds[i], req_kernel, arg); - if (ret < 0) - break; - } - } else { - ret = ioctl(vhostfd, req_kernel, arg); + + /* restore index back to queue index */ + file->index = index; + + return 0; +} + +static int +vhost_kernel_set_vring_kick(struct virtio_user_dev *dev, struct vhost_vring_file *file) +{ + return vhost_kernel_set_vring_file(dev, VHOST_SET_VRING_KICK, file); +} + +static int +vhost_kernel_set_vring_call(struct virtio_user_dev *dev, struct vhost_vring_file *file) +{ + return vhost_kernel_set_vring_file(dev, VHOST_SET_VRING_CALL, file); +} + +static int +vhost_kernel_set_vring_addr(struct virtio_user_dev *dev, struct vhost_vring_addr *addr) +{ + int ret, fd; + unsigned int index = addr->index; + struct vhost_kernel_data *data = dev->backend_data; + + /* Convert from queue index to queue-pair & offset */ + fd = data->vhostfds[addr->index / 2]; + addr->index %= 2; + + ret = vhost_kernel_ioctl(fd, VHOST_SET_VRING_ADDR, addr); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Failed to set vring address"); + return -1; } - if (ret < 0) - PMD_DRV_LOG(ERR, "%s failed: %s", - vhost_msg_strings[req], strerror(errno)); + /* restore index back to queue index */ + addr->index = index; + + return 0; +} + +static int +vhost_kernel_get_status(struct virtio_user_dev *dev __rte_unused, uint8_t *status __rte_unused) +{ + return -ENOTSUP; +} - return ret; +static int +vhost_kernel_set_status(struct virtio_user_dev *dev __rte_unused, uint8_t status __rte_unused) +{ + return -ENOTSUP; } /** @@ -325,21 +364,82 @@ static int vhost_kernel_setup(struct virtio_user_dev *dev) { int vhostfd; - uint32_t i; + uint32_t q, i; + struct vhost_kernel_data *data; + + data = malloc(sizeof(*data)); + if (!data) { + PMD_INIT_LOG(ERR, "(%s) Failed to allocate Vhost-kernel data", dev->path); + return -1; + } + + data->vhostfds = malloc(dev->max_queue_pairs * sizeof(int)); + if (!data->vhostfds) { + PMD_INIT_LOG(ERR, "(%s) Failed to allocate Vhost FDs", dev->path); + goto err_data; + } + data->tapfds = malloc(dev->max_queue_pairs * sizeof(int)); + if (!data->tapfds) { + PMD_INIT_LOG(ERR, "(%s) Failed to allocate TAP FDs", dev->path); + goto err_vhostfds; + } + + for (q = 0; q < dev->max_queue_pairs; ++q) { + data->vhostfds[q] = -1; + data->tapfds[q] = -1; + } get_vhost_kernel_max_regions(); for (i = 0; i < dev->max_queue_pairs; ++i) { vhostfd = open(dev->path, O_RDWR); if (vhostfd < 0) { - PMD_DRV_LOG(ERR, "fail to open %s, %s", - dev->path, strerror(errno)); - return -1; + PMD_DRV_LOG(ERR, "fail to open %s, %s", dev->path, strerror(errno)); + goto err_tapfds; } - dev->vhostfds[i] = vhostfd; + data->vhostfds[i] = vhostfd; } + dev->backend_data = data; + + return 0; + +err_tapfds: + for (i = 0; i < dev->max_queue_pairs; i++) + if (data->vhostfds[i] >= 0) + close(data->vhostfds[i]); + + free(data->tapfds); +err_vhostfds: + free(data->vhostfds); +err_data: + free(data); + + return -1; +} + +static int +vhost_kernel_destroy(struct virtio_user_dev *dev) +{ + struct vhost_kernel_data *data = dev->backend_data; + uint32_t i; + + if (!data) + return 0; + + 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->vhostfds); + free(data->tapfds); + free(data); + dev->backend_data = NULL; + return 0; } @@ -375,14 +475,15 @@ vhost_kernel_enable_queue_pair(struct virtio_user_dev *dev, int vhostfd; int tapfd; int req_mq = (dev->max_queue_pairs > 1); + struct vhost_kernel_data *data = dev->backend_data; - vhostfd = dev->vhostfds[pair_idx]; + vhostfd = data->vhostfds[pair_idx]; if (dev->qp_enabled[pair_idx] == enable) return 0; if (!enable) { - tapfd = dev->tapfds[pair_idx]; + 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; @@ -395,8 +496,8 @@ vhost_kernel_enable_queue_pair(struct virtio_user_dev *dev, return 0; } - if (dev->tapfds[pair_idx] >= 0) { - tapfd = dev->tapfds[pair_idx]; + 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) { @@ -419,7 +520,7 @@ vhost_kernel_enable_queue_pair(struct virtio_user_dev *dev, return -1; } - dev->tapfds[pair_idx] = tapfd; + data->tapfds[pair_idx] = tapfd; set_backend: if (vhost_kernel_set_backend(vhostfd, tapfd) < 0) { @@ -431,8 +532,32 @@ set_backend: return 0; } +static int +vhost_kernel_get_backend_features(uint64_t *features) +{ + *features = 0; + + return 0; +} + +static int +vhost_kernel_update_link_state(struct virtio_user_dev *dev __rte_unused) +{ + /* Nothing to update (Maybe get TAP interface link state?) */ + return 0; +} + +static int +vhost_kernel_get_intr_fd(struct virtio_user_dev *dev __rte_unused) +{ + /* No link state interrupt with Vhost-kernel */ + return -1; +} + struct virtio_user_backend_ops virtio_ops_kernel = { .setup = vhost_kernel_setup, + .destroy = vhost_kernel_destroy, + .get_backend_features = vhost_kernel_get_backend_features, .set_owner = vhost_kernel_set_owner, .get_features = vhost_kernel_get_features, .set_features = vhost_kernel_set_features, @@ -440,6 +565,12 @@ struct virtio_user_backend_ops virtio_ops_kernel = { .set_vring_num = vhost_kernel_set_vring_num, .set_vring_base = vhost_kernel_set_vring_base, .get_vring_base = vhost_kernel_get_vring_base, - .send_request = vhost_kernel_send_request, - .enable_qp = vhost_kernel_enable_queue_pair + .set_vring_call = vhost_kernel_set_vring_call, + .set_vring_kick = vhost_kernel_set_vring_kick, + .set_vring_addr = vhost_kernel_set_vring_addr, + .get_status = vhost_kernel_get_status, + .set_status = vhost_kernel_set_status, + .enable_qp = vhost_kernel_enable_queue_pair, + .update_link_state = vhost_kernel_update_link_state, + .get_intr_fd = vhost_kernel_get_intr_fd, };