RE: kvmtool: vhost MQ support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Vitaly,
 Thanks for your quick feedback, sorry for the several formatting issues! I applied all your comments to the attached patch.
 For the moment, I would prefer to keep 'vhost_fd', but happy to remove it if you would like me to do so -- just let me know.
Cheers,
Antonio

-----Original Message-----
From: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx> 
Sent: Tuesday, October 6, 2020 12:58 PM
To: BARBALACE Antonio <antonio.barbalace@xxxxxxxx>
Cc: will@xxxxxxxxxx; julien.thierry.kdev@xxxxxxxxx; kvm@xxxxxxxxxxxxxxx
Subject: Re: kvmtool: vhost MQ support

BARBALACE Antonio <antonio.barbalace@xxxxxxxx> writes:

> This patch enables vhost MQ to support in kvmtool without any Linux kernel modification.
> The patch takes the same approach as QEMU -- for each queue pair a new /dev/vhost-net fd is created.
> Fds are kept in ndev->vhost_fds, with ndev->vhost_fd == ndev->vhost_fds[0] (to avoid further modification to the existent source code).
> Thanks, Antonio Barbalace
> The University of Edinburgh is a charitable body, registered in Scotland, with registration number SC005336.
> diff --git a/virtio/net.c b/virtio/net.c index 1ee3c19..bae3019 100644
> --- a/virtio/net.c
> +++ b/virtio/net.c
> @@ -58,6 +58,7 @@ struct net_dev {
>  	u32				features, queue_pairs;
>  
>  	int				vhost_fd;
> +	int				vhost_fds[VIRTIO_NET_NUM_QUEUES];
>  	int				tap_fd;
>  	char				tap_name[IFNAMSIZ];
>  	bool				tap_ufo;
> @@ -512,6 +513,7 @@ static int virtio_net__vhost_set_features(struct 
> net_dev *ndev)  {
>  	u64 features = 1UL << VIRTIO_RING_F_EVENT_IDX;
>  	u64 vhost_features;
> +	int i, r = 0;
>  
>  	if (ioctl(ndev->vhost_fd, VHOST_GET_FEATURES, &vhost_features) != 0)
>  		die_perror("VHOST_GET_FEATURES failed"); @@ -521,7 +523,9 @@ static 
> int virtio_net__vhost_set_features(struct net_dev *ndev)
>  			has_virtio_feature(ndev, VIRTIO_NET_F_MRG_RXBUF))
>  		features |= 1UL << VIRTIO_NET_F_MRG_RXBUF;
>  
> -	return ioctl(ndev->vhost_fd, VHOST_SET_FEATURES, &features);
> +	for (i=0; ((u32)i < ndev->queue_pairs) && (r >= 0); i++)

Neither a virtio nor a kvmtool person here, just some comments about the style below.

Nit: more spaces needed:
	for (i = 0; 

(u32) cast is not really needed because ndev->queue_pairs is caped with VIRTIO_NET_NUM_QUEUES and 

ndev->queue_pairs = max(1, min(VIRTIO_NET_NUM_QUEUES, params->mq));

alternatively, you can just declare i as 'u32'.

> +		r = ioctl(ndev->vhost_fds[i], VHOST_SET_FEATURES, &features);

To improve the readability I'd suggest to write this as

	for (i=0; i < ndev->queue_pairs; i++) {
		r = ioctl(ndev->vhost_fds[i], VHOST_SET_FEATURES, &features);
		if (r)
			break;
	}


> +	return r;
>  }
>  
>  static void set_guest_features(struct kvm *kvm, void *dev, u32 
> features) @@ -578,7 +582,7 @@ static bool is_ctrl_vq(struct net_dev 
> *ndev, u32 vq)  static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 page_size, u32 align,
>  		   u32 pfn)
>  {
> -	struct vhost_vring_state state = { .index = vq };
> +	struct vhost_vring_state state = { .index = (vq %2) };

Nit: superfluous parentheses

>  	struct net_dev_queue *net_queue;
>  	struct vhost_vring_addr addr;
>  	struct net_dev *ndev = dev;
> @@ -619,23 +623,24 @@ static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 page_size, u32 align,
>  	if (queue->endian != VIRTIO_ENDIAN_HOST)
>  		die_perror("VHOST requires the same endianness in guest and host");
>  
> -	state.num = queue->vring.num;
> -	r = ioctl(ndev->vhost_fd, VHOST_SET_VRING_NUM, &state);
> +	state.num = queue->vring.num; //number of decriptors

I don't see C++ style comments anywhere in this file, use /* */ instead.

> +        r = ioctl(ndev->vhost_fds[(vq /2)], VHOST_SET_VRING_NUM, 
> + &state);

Indentation. Also, you seem to be using 'vq / 2' a lot, maybe assign this to a local variable.

>  	if (r < 0)
>  		die_perror("VHOST_SET_VRING_NUM failed");
> -	state.num = 0;
> -	r = ioctl(ndev->vhost_fd, VHOST_SET_VRING_BASE, &state);
> +
> +	state.num = 0; //descriptors base

Comment style.

> +	r = ioctl(ndev->vhost_fds[(vq /2)], VHOST_SET_VRING_BASE, &state);
>  	if (r < 0)
>  		die_perror("VHOST_SET_VRING_BASE failed");
>  
>  	addr = (struct vhost_vring_addr) {
> -		.index = vq,
> +		.index = (vq %2),
>  		.desc_user_addr = (u64)(unsigned long)queue->vring.desc,
>  		.avail_user_addr = (u64)(unsigned long)queue->vring.avail,
>  		.used_user_addr = (u64)(unsigned long)queue->vring.used,
>  	};
>  
> -	r = ioctl(ndev->vhost_fd, VHOST_SET_VRING_ADDR, &addr);
> +	r = ioctl(ndev->vhost_fds[(vq /2)], VHOST_SET_VRING_ADDR, &addr);
>  	if (r < 0)
>  		die_perror("VHOST_SET_VRING_ADDR failed");
>  
> @@ -659,7 +664,7 @@ static void exit_vq(struct kvm *kvm, void *dev, u32 vq)
>  	 */
>  	if (ndev->vhost_fd && !is_ctrl_vq(ndev, vq)) {
>  		pr_warning("Cannot reset VHOST queue");
> -		ioctl(ndev->vhost_fd, VHOST_RESET_OWNER);
> +		ioctl(ndev->vhost_fds[(vq /2)], VHOST_RESET_OWNER);
>  		return;
>  	}
>  
> @@ -682,7 +687,7 @@ static void notify_vq_gsi(struct kvm *kvm, void *dev, u32 vq, u32 gsi)
>  		return;
>  
>  	file = (struct vhost_vring_file) {
> -		.index	= vq,
> +		.index	= (vq % 2),
>  		.fd	= eventfd(0, 0),
>  	};
>  
> @@ -693,31 +698,32 @@ static void notify_vq_gsi(struct kvm *kvm, void *dev, u32 vq, u32 gsi)
>  	queue->irqfd = file.fd;
>  	queue->gsi = gsi;
>  
> -	r = ioctl(ndev->vhost_fd, VHOST_SET_VRING_CALL, &file);
> +	r = ioctl(ndev->vhost_fds[(vq /2)], VHOST_SET_VRING_CALL, &file);
>  	if (r < 0)
>  		die_perror("VHOST_SET_VRING_CALL failed");
> +
>  	file.fd = ndev->tap_fd;
> -	r = ioctl(ndev->vhost_fd, VHOST_NET_SET_BACKEND, &file);
> +	r = ioctl(ndev->vhost_fds[(vq /2)], VHOST_NET_SET_BACKEND, &file);
>  	if (r != 0)
>  		die("VHOST_NET_SET_BACKEND failed %d", errno);
> -
>  }
>  
>  static void notify_vq_eventfd(struct kvm *kvm, void *dev, u32 vq, u32 
> efd)  {
>  	struct net_dev *ndev = dev;
>  	struct vhost_vring_file file = {
> -		.index	= vq,
> +		.index	= (vq % 2),
>  		.fd	= efd,
>  	};
>  	int r;
>  
> -	if (ndev->vhost_fd == 0 || is_ctrl_vq(ndev, vq))
> +	if (ndev->vhost_fd == 0 || is_ctrl_vq(ndev, vq)) {
>  		return;
> +	}
> +	r = ioctl(ndev->vhost_fds[(vq /2)], VHOST_SET_VRING_KICK, &file);
>  
> -	r = ioctl(ndev->vhost_fd, VHOST_SET_VRING_KICK, &file);
>  	if (r < 0)
> -		die_perror("VHOST_SET_VRING_KICK failed");
> +		die_perror("VHOST_SET_VRING_KICK failed test");

What is this 'failed test' about? Stray change?

>  }
>  
>  static int notify_vq(struct kvm *kvm, void *dev, u32 vq) @@ -777,10 
> +783,6 @@ static void virtio_net__vhost_init(struct kvm *kvm, struct net_dev *ndev)
>  	struct vhost_memory *mem;
>  	int r, i;
>  
> -	ndev->vhost_fd = open("/dev/vhost-net", O_RDWR);
> -	if (ndev->vhost_fd < 0)
> -		die_perror("Failed openning vhost-net device");
> -
>  	mem = calloc(1, sizeof(*mem) + kvm->mem_slots * sizeof(struct vhost_memory_region));
>  	if (mem == NULL)
>  		die("Failed allocating memory for vhost memory map"); @@ -796,13 
> +798,22 @@ static void virtio_net__vhost_init(struct kvm *kvm, struct net_dev *ndev)
>  	}
>  	mem->nregions = i;
>  
> -	r = ioctl(ndev->vhost_fd, VHOST_SET_OWNER);
> -	if (r != 0)
> -		die_perror("VHOST_SET_OWNER failed");
> +	for (i=0; ((u32)i < ndev->queue_pairs) && 
> +			(i < VIRTIO_NET_NUM_QUEUES); i++) {
>  

Same as above.

> -	r = ioctl(ndev->vhost_fd, VHOST_SET_MEM_TABLE, mem);
> -	if (r != 0)
> -		die_perror("VHOST_SET_MEM_TABLE failed");
> +		ndev->vhost_fds[i] = open("/dev/vhost-net", O_RDWR);
> +	        if (ndev->vhost_fds[i] < 0)
> +			die_perror("Failed openning vhost-net device");
> +
> +		r = ioctl(ndev->vhost_fds[i], VHOST_SET_OWNER);
> +		if (r != 0)
> +			die_perror("VHOST_SET_OWNER failed");
> +	
> +		r = ioctl(ndev->vhost_fds[i], VHOST_SET_MEM_TABLE, mem);
> +		if (r != 0)
> +			die_perror("VHOST_SET_MEM_TABLE failed");
> +	}
> +	ndev->vhost_fd = ndev->vhost_fds[0];

Do we actually need 'vhost_fd' at all, can we just use vhost_fds[0] in a few places where it is still present?

>  
>  	ndev->vdev.use_vhost = true;
>  
> @@ -966,7 +977,6 @@ static int virtio_net__init_one(struct virtio_net_params *params)
>  				   "falling back to %s.", params->trans,
>  				   virtio_trans_name(trans));
>  	}
> -

Stray change?

>  	r = virtio_init(params->kvm, ndev, &ndev->vdev, ops, trans,
>  			PCI_DEVICE_ID_VIRTIO_NET, VIRTIO_ID_NET, PCI_CLASS_NET);
>  	if (r < 0) {
> diff --git a/virtio/pci.c b/virtio/pci.c index c652949..7a1532b 100644
> --- a/virtio/pci.c
> +++ b/virtio/pci.c
> @@ -44,7 +44,8 @@ static int virtio_pci__init_ioeventfd(struct kvm *kvm, struct virtio_device *vde
>  	 * Vhost will poll the eventfd in host kernel side, otherwise we
>  	 * need to poll in userspace.
>  	 */
> -	if (!vdev->use_vhost)
> +	if ( (!vdev->use_vhost) ||

Xen coding style detected :-) Just

	if (!vdev->use_vhost || (vdev->ops->get_vq_count(kvm, vpci->dev) = vq + 1)

would do fine.

> +		((u32)vdev->ops->get_vq_count(kvm, vpci->dev)==(vq+1)) )
>  		flags |= IOEVENTFD_FLAG_USER_POLL;
>  
>  	/* ioport */

--
Vitaly

Attachment: kvmtool-vhost_mq-20201007.patch
Description: kvmtool-vhost_mq-20201007.patch


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux