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
						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