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:
		
				
					committed by
					
						
						Michael S. Tsirkin
					
				
			
			
				
	
			
			
			
						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);
 | 
					        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;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										105
									
								
								net/vhost-vdpa.c
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								net/vhost-vdpa.c
									
									
									
									
									
								
							@@ -18,6 +18,7 @@
 | 
				
			|||||||
#include "qemu/error-report.h"
 | 
					#include "qemu/error-report.h"
 | 
				
			||||||
#include "qemu/option.h"
 | 
					#include "qemu/option.h"
 | 
				
			||||||
#include "qapi/error.h"
 | 
					#include "qapi/error.h"
 | 
				
			||||||
 | 
					#include <linux/vhost.h>
 | 
				
			||||||
#include <sys/ioctl.h>
 | 
					#include <sys/ioctl.h>
 | 
				
			||||||
#include <err.h>
 | 
					#include <err.h>
 | 
				
			||||||
#include "standard-headers/linux/virtio_net.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_HOST_UFO,
 | 
				
			||||||
    VIRTIO_NET_F_MRG_RXBUF,
 | 
					    VIRTIO_NET_F_MRG_RXBUF,
 | 
				
			||||||
    VIRTIO_NET_F_MTU,
 | 
					    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_IOMMU_PLATFORM,
 | 
				
			||||||
    VIRTIO_F_RING_PACKED,
 | 
					    VIRTIO_F_RING_PACKED,
 | 
				
			||||||
    VIRTIO_NET_F_RSS,
 | 
					    VIRTIO_NET_F_RSS,
 | 
				
			||||||
@@ -81,7 +90,8 @@ static int vhost_vdpa_net_check_device_id(struct vhost_net *net)
 | 
				
			|||||||
    return ret;
 | 
					    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;
 | 
					    VhostNetOptions options;
 | 
				
			||||||
    struct vhost_net *net = NULL;
 | 
					    struct vhost_net *net = NULL;
 | 
				
			||||||
@@ -94,7 +104,7 @@ static int vhost_vdpa_add(NetClientState *ncs, void *be)
 | 
				
			|||||||
    options.net_backend = ncs;
 | 
					    options.net_backend = ncs;
 | 
				
			||||||
    options.opaque      = be;
 | 
					    options.opaque      = be;
 | 
				
			||||||
    options.busyloop_timeout = 0;
 | 
					    options.busyloop_timeout = 0;
 | 
				
			||||||
    options.nvqs = 2;
 | 
					    options.nvqs = nvqs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    net = vhost_net_init(&options);
 | 
					    net = vhost_net_init(&options);
 | 
				
			||||||
    if (!net) {
 | 
					    if (!net) {
 | 
				
			||||||
@@ -172,18 +182,28 @@ static NetClientInfo net_vhost_vdpa_info = {
 | 
				
			|||||||
static NetClientState *net_vhost_vdpa_init(NetClientState *peer,
 | 
					static NetClientState *net_vhost_vdpa_init(NetClientState *peer,
 | 
				
			||||||
                                           const char *device,
 | 
					                                           const char *device,
 | 
				
			||||||
                                           const char *name,
 | 
					                                           const char *name,
 | 
				
			||||||
                                           int vdpa_device_fd)
 | 
					                                           int vdpa_device_fd,
 | 
				
			||||||
 | 
					                                           int queue_pair_index,
 | 
				
			||||||
 | 
					                                           int nvqs,
 | 
				
			||||||
 | 
					                                           bool is_datapath)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    NetClientState *nc = NULL;
 | 
					    NetClientState *nc = NULL;
 | 
				
			||||||
    VhostVDPAState *s;
 | 
					    VhostVDPAState *s;
 | 
				
			||||||
    int ret = 0;
 | 
					    int ret = 0;
 | 
				
			||||||
    assert(name);
 | 
					    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);
 | 
					    snprintf(nc->info_str, sizeof(nc->info_str), TYPE_VHOST_VDPA);
 | 
				
			||||||
    s = DO_UPCAST(VhostVDPAState, nc, nc);
 | 
					    s = DO_UPCAST(VhostVDPAState, nc, nc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->vhost_vdpa.device_fd = vdpa_device_fd;
 | 
					    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) {
 | 
					    if (ret) {
 | 
				
			||||||
        qemu_del_net_client(nc);
 | 
					        qemu_del_net_client(nc);
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
@@ -191,12 +211,52 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer,
 | 
				
			|||||||
    return nc;
 | 
					    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,
 | 
					int net_init_vhost_vdpa(const Netdev *netdev, const char *name,
 | 
				
			||||||
                        NetClientState *peer, Error **errp)
 | 
					                        NetClientState *peer, Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const NetdevVhostVDPAOptions *opts;
 | 
					    const NetdevVhostVDPAOptions *opts;
 | 
				
			||||||
    int vdpa_device_fd;
 | 
					    int vdpa_device_fd;
 | 
				
			||||||
    NetClientState *nc;
 | 
					    NetClientState **ncs, *nc;
 | 
				
			||||||
 | 
					    int queue_pairs, i, has_cvq = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert(netdev->type == NET_CLIENT_DRIVER_VHOST_VDPA);
 | 
					    assert(netdev->type == NET_CLIENT_DRIVER_VHOST_VDPA);
 | 
				
			||||||
    opts = &netdev->u.vhost_vdpa;
 | 
					    opts = &netdev->u.vhost_vdpa;
 | 
				
			||||||
@@ -206,11 +266,38 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name,
 | 
				
			|||||||
        return -errno;
 | 
					        return -errno;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    nc = net_vhost_vdpa_init(peer, TYPE_VHOST_VDPA, name, vdpa_device_fd);
 | 
					    queue_pairs = vhost_vdpa_get_max_queue_pairs(vdpa_device_fd,
 | 
				
			||||||
    if (!nc) {
 | 
					                                                 &has_cvq, errp);
 | 
				
			||||||
 | 
					    if (queue_pairs < 0) {
 | 
				
			||||||
        qemu_close(vdpa_device_fd);
 | 
					        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;
 | 
					    return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err:
 | 
				
			||||||
 | 
					    if (i) {
 | 
				
			||||||
 | 
					        qemu_del_net_client(ncs[0]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    qemu_close(vdpa_device_fd);
 | 
				
			||||||
 | 
					    g_free(ncs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user