vhost-vdpa: multiqueue support
This patch implements the multiqueue support for vhost-vdpa. This is done simply by reading the number of queue pairs from the config space and initialize the datapath and control path net client. Signed-off-by: Jason Wang <jasowang@redhat.com> Message-Id: <20211020045600.16082-11-jasowang@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
22288fe5a3
commit
402378407d
@ -632,7 +632,7 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
|
||||
vhost_vdpa_host_notifiers_uninit(dev, dev->nvqs);
|
||||
}
|
||||
|
||||
if (vhost_vdpa_one_time_request(dev)) {
|
||||
if (dev->vq_index + dev->nvqs != dev->last_index) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
105
net/vhost-vdpa.c
105
net/vhost-vdpa.c
@ -18,6 +18,7 @@
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/option.h"
|
||||
#include "qapi/error.h"
|
||||
#include <linux/vhost.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <err.h>
|
||||
#include "standard-headers/linux/virtio_net.h"
|
||||
@ -51,6 +52,14 @@ const int vdpa_feature_bits[] = {
|
||||
VIRTIO_NET_F_HOST_UFO,
|
||||
VIRTIO_NET_F_MRG_RXBUF,
|
||||
VIRTIO_NET_F_MTU,
|
||||
VIRTIO_NET_F_CTRL_RX,
|
||||
VIRTIO_NET_F_CTRL_RX_EXTRA,
|
||||
VIRTIO_NET_F_CTRL_VLAN,
|
||||
VIRTIO_NET_F_GUEST_ANNOUNCE,
|
||||
VIRTIO_NET_F_CTRL_MAC_ADDR,
|
||||
VIRTIO_NET_F_RSS,
|
||||
VIRTIO_NET_F_MQ,
|
||||
VIRTIO_NET_F_CTRL_VQ,
|
||||
VIRTIO_F_IOMMU_PLATFORM,
|
||||
VIRTIO_F_RING_PACKED,
|
||||
VIRTIO_NET_F_RSS,
|
||||
@ -81,7 +90,8 @@ static int vhost_vdpa_net_check_device_id(struct vhost_net *net)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vhost_vdpa_add(NetClientState *ncs, void *be)
|
||||
static int vhost_vdpa_add(NetClientState *ncs, void *be,
|
||||
int queue_pair_index, int nvqs)
|
||||
{
|
||||
VhostNetOptions options;
|
||||
struct vhost_net *net = NULL;
|
||||
@ -94,7 +104,7 @@ static int vhost_vdpa_add(NetClientState *ncs, void *be)
|
||||
options.net_backend = ncs;
|
||||
options.opaque = be;
|
||||
options.busyloop_timeout = 0;
|
||||
options.nvqs = 2;
|
||||
options.nvqs = nvqs;
|
||||
|
||||
net = vhost_net_init(&options);
|
||||
if (!net) {
|
||||
@ -172,18 +182,28 @@ static NetClientInfo net_vhost_vdpa_info = {
|
||||
static NetClientState *net_vhost_vdpa_init(NetClientState *peer,
|
||||
const char *device,
|
||||
const char *name,
|
||||
int vdpa_device_fd)
|
||||
int vdpa_device_fd,
|
||||
int queue_pair_index,
|
||||
int nvqs,
|
||||
bool is_datapath)
|
||||
{
|
||||
NetClientState *nc = NULL;
|
||||
VhostVDPAState *s;
|
||||
int ret = 0;
|
||||
assert(name);
|
||||
nc = qemu_new_net_client(&net_vhost_vdpa_info, peer, device, name);
|
||||
if (is_datapath) {
|
||||
nc = qemu_new_net_client(&net_vhost_vdpa_info, peer, device,
|
||||
name);
|
||||
} else {
|
||||
nc = qemu_new_net_control_client(&net_vhost_vdpa_info, peer,
|
||||
device, name);
|
||||
}
|
||||
snprintf(nc->info_str, sizeof(nc->info_str), TYPE_VHOST_VDPA);
|
||||
s = DO_UPCAST(VhostVDPAState, nc, nc);
|
||||
|
||||
s->vhost_vdpa.device_fd = vdpa_device_fd;
|
||||
ret = vhost_vdpa_add(nc, (void *)&s->vhost_vdpa);
|
||||
s->vhost_vdpa.index = queue_pair_index;
|
||||
ret = vhost_vdpa_add(nc, (void *)&s->vhost_vdpa, queue_pair_index, nvqs);
|
||||
if (ret) {
|
||||
qemu_del_net_client(nc);
|
||||
return NULL;
|
||||
@ -191,12 +211,52 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer,
|
||||
return nc;
|
||||
}
|
||||
|
||||
static int vhost_vdpa_get_max_queue_pairs(int fd, int *has_cvq, Error **errp)
|
||||
{
|
||||
unsigned long config_size = offsetof(struct vhost_vdpa_config, buf);
|
||||
struct vhost_vdpa_config *config;
|
||||
__virtio16 *max_queue_pairs;
|
||||
uint64_t features;
|
||||
int ret;
|
||||
|
||||
ret = ioctl(fd, VHOST_GET_FEATURES, &features);
|
||||
if (ret) {
|
||||
error_setg(errp, "Fail to query features from vhost-vDPA device");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (features & (1 << VIRTIO_NET_F_CTRL_VQ)) {
|
||||
*has_cvq = 1;
|
||||
} else {
|
||||
*has_cvq = 0;
|
||||
}
|
||||
|
||||
if (features & (1 << VIRTIO_NET_F_MQ)) {
|
||||
config = g_malloc0(config_size + sizeof(*max_queue_pairs));
|
||||
config->off = offsetof(struct virtio_net_config, max_virtqueue_pairs);
|
||||
config->len = sizeof(*max_queue_pairs);
|
||||
|
||||
ret = ioctl(fd, VHOST_VDPA_GET_CONFIG, config);
|
||||
if (ret) {
|
||||
error_setg(errp, "Fail to get config from vhost-vDPA device");
|
||||
return -ret;
|
||||
}
|
||||
|
||||
max_queue_pairs = (__virtio16 *)&config->buf;
|
||||
|
||||
return lduw_le_p(max_queue_pairs);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int net_init_vhost_vdpa(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp)
|
||||
{
|
||||
const NetdevVhostVDPAOptions *opts;
|
||||
int vdpa_device_fd;
|
||||
NetClientState *nc;
|
||||
NetClientState **ncs, *nc;
|
||||
int queue_pairs, i, has_cvq = 0;
|
||||
|
||||
assert(netdev->type == NET_CLIENT_DRIVER_VHOST_VDPA);
|
||||
opts = &netdev->u.vhost_vdpa;
|
||||
@ -206,11 +266,38 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name,
|
||||
return -errno;
|
||||
}
|
||||
|
||||
nc = net_vhost_vdpa_init(peer, TYPE_VHOST_VDPA, name, vdpa_device_fd);
|
||||
if (!nc) {
|
||||
queue_pairs = vhost_vdpa_get_max_queue_pairs(vdpa_device_fd,
|
||||
&has_cvq, errp);
|
||||
if (queue_pairs < 0) {
|
||||
qemu_close(vdpa_device_fd);
|
||||
return -1;
|
||||
return queue_pairs;
|
||||
}
|
||||
|
||||
ncs = g_malloc0(sizeof(*ncs) * queue_pairs);
|
||||
|
||||
for (i = 0; i < queue_pairs; i++) {
|
||||
ncs[i] = net_vhost_vdpa_init(peer, TYPE_VHOST_VDPA, name,
|
||||
vdpa_device_fd, i, 2, true);
|
||||
if (!ncs[i])
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (has_cvq) {
|
||||
nc = net_vhost_vdpa_init(peer, TYPE_VHOST_VDPA, name,
|
||||
vdpa_device_fd, i, 1, false);
|
||||
if (!nc)
|
||||
goto err;
|
||||
}
|
||||
|
||||
g_free(ncs);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (i) {
|
||||
qemu_del_net_client(ncs[0]);
|
||||
}
|
||||
qemu_close(vdpa_device_fd);
|
||||
g_free(ncs);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user