#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;
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
{
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;
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 */
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
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;
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;
{
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);
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;
}
/**
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;
}
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;
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) {
return -1;
}
- dev->tapfds[pair_idx] = tapfd;
+ data->tapfds[pair_idx] = tapfd;
set_backend:
if (vhost_kernel_set_backend(vhostfd, tapfd) < 0) {
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,
.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,
};