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); | ||||
|     } | ||||
|  | ||||
|     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; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user