DPDK patches and discussions
 help / color / mirror / Atom feed
From: Maxime Coquelin <maxime.coquelin@redhat.com>
To: Srujana Challa <schalla@marvell.com>, dev@dpdk.org, chenbox@nvidia.com
Cc: jerinj@marvell.com, vattunuru@marvell.com
Subject: Re: [PATCH 1/2] net/virtio-user: improve kick performance with notification area mapping
Date: Thu, 11 Jan 2024 15:14:13 +0100	[thread overview]
Message-ID: <d3cbcd44-1e5e-4bf4-bb81-f332eb2cc3fe@redhat.com> (raw)
In-Reply-To: <20231208053121.152929-1-schalla@marvell.com>

Hi Srujana,

Thanks for your contribution!
Is it possible to provide information on which hardware it can be tested
on?

On 12/8/23 06:31, Srujana Challa wrote:
> This patch introduces new virtio-user callback to map the vq
> notification area and implements it for the vhost-vDPA backend.
> This is simply done by using mmap()/munmap() for
> the vhost-vDPA fd.
> 
> This patch also adds a parameter for configuring feature bit
> VIRTIO_NET_F_NOTIFICATION_DATA. If feature is disabled, also

VIRTIO_F_NOTIFICATION_DATA*

> update corresponding unsupported feature bit. And also adds
> code to write to queue notify address in notify callback.
> This will help in increasing the kick performance.

Do you have any number about the performance improvement?

> Signed-off-by: Srujana Challa <schalla@marvell.com>
> ---
>   doc/guides/nics/virtio.rst                    |  5 ++
>   drivers/net/virtio/virtio_user/vhost.h        |  1 +
>   drivers/net/virtio/virtio_user/vhost_vdpa.c   | 56 ++++++++++++++++++
>   .../net/virtio/virtio_user/virtio_user_dev.c  | 52 +++++++++++++++--
>   .../net/virtio/virtio_user/virtio_user_dev.h  |  5 +-
>   drivers/net/virtio/virtio_user_ethdev.c       | 57 ++++++++++++++++---
>   6 files changed, 162 insertions(+), 14 deletions(-)
> 
> diff --git a/doc/guides/nics/virtio.rst b/doc/guides/nics/virtio.rst
> index c22ce56a02..11dd6359e5 100644
> --- a/doc/guides/nics/virtio.rst
> +++ b/doc/guides/nics/virtio.rst
> @@ -349,6 +349,11 @@ Below devargs are supported by the virtio-user vdev:
>       election.
>       (Default: 0 (disabled))
>   
> +#.  ``notification_data``:
> +
> +    It is used to enable virtio device notification data feature.
> +    (Default: 1 (enabled))

Is there any reason currently to make it configurable?

As it is enabled by default, I guess we want it to be negociated if the
device supports it.

Let's remove the devarg for now, and we can revisit if the need arise?

> +
>   Virtio paths Selection and Usage
>   --------------------------------
>   
> diff --git a/drivers/net/virtio/virtio_user/vhost.h b/drivers/net/virtio/virtio_user/vhost.h
> index f817cab77a..1bce00c7ac 100644
> --- a/drivers/net/virtio/virtio_user/vhost.h
> +++ b/drivers/net/virtio/virtio_user/vhost.h
> @@ -90,6 +90,7 @@ struct virtio_user_backend_ops {
>   	int (*server_disconnect)(struct virtio_user_dev *dev);
>   	int (*server_reconnect)(struct virtio_user_dev *dev);
>   	int (*get_intr_fd)(struct virtio_user_dev *dev);
> +	int (*map_notification_area)(struct virtio_user_dev *dev, bool map);
>   };
>   
>   extern struct virtio_user_backend_ops virtio_ops_user;
> diff --git a/drivers/net/virtio/virtio_user/vhost_vdpa.c b/drivers/net/virtio/virtio_user/vhost_vdpa.c
> index 2c36b26224..1eb0f9ec48 100644
> --- a/drivers/net/virtio/virtio_user/vhost_vdpa.c
> +++ b/drivers/net/virtio/virtio_user/vhost_vdpa.c
> @@ -5,6 +5,7 @@
>   #include <sys/ioctl.h>
>   #include <sys/types.h>
>   #include <sys/stat.h>
> +#include <sys/mman.h>
>   #include <fcntl.h>
>   #include <stdlib.h>
>   #include <unistd.h>
> @@ -622,6 +623,60 @@ vhost_vdpa_get_intr_fd(struct virtio_user_dev *dev __rte_unused)
>   	return -1;
>   }
>   
> +static int
> +unmap_notification_area(struct virtio_user_dev *dev, int nr_vrings)
> +{
> +	int i;
> +
> +	for (i = 0; i < nr_vrings; i++) {
> +		if (dev->notify_area[i])
> +			munmap(dev->notify_area[i], getpagesize());
> +	}
> +	free(dev->notify_area);
> +
> +	return 0;
> +}
> +
> +static int
> +vhost_vdpa_map_notification_area(struct virtio_user_dev *dev, bool map)
> +{
> +	struct vhost_vdpa_data *data = dev->backend_data;
> +	int nr_vrings, i, page_size = getpagesize();
> +	uint16_t **notify_area;
> +
> +	nr_vrings = dev->max_queue_pairs * 2;
> +	if (dev->device_features & (1ull << VIRTIO_NET_F_CTRL_VQ))
> +		nr_vrings++;
> +
> +	if (!map)
> +		return unmap_notification_area(dev, nr_vrings);
> +
> +	notify_area = malloc(nr_vrings * sizeof(*notify_area));
> +	if (!notify_area) {
> +		PMD_DRV_LOG(ERR, "(%s) Failed to allocate notify area array", dev->path);
> +		return -1;
> +	}

Add new line here.

> +	for (i = 0; i < nr_vrings; i++) {
> +		notify_area[i] = mmap(NULL, page_size, PROT_WRITE, MAP_SHARED | MAP_FILE,
> +				      data->vhostfd, i * page_size);
> +		if (notify_area[i] == MAP_FAILED) {
> +			PMD_DRV_LOG(ERR, "(%s) Map failed for notify address of queue %d\n",
> +				    dev->path, i);
> +			goto map_err;
> +		}
> +	}
> +	dev->notify_area = notify_area;
> +
> +	return 0;
> +
> +map_err:
> +	i--;

I would move this before the goto map_err;

> +	for (; i >= 0; i--)
> +		munmap(notify_area[i], page_size);
> +	free(notify_area);

New line here.

> +	return -1;
> +}
> +
>   struct virtio_user_backend_ops virtio_ops_vdpa = {
>   	.setup = vhost_vdpa_setup,
>   	.destroy = vhost_vdpa_destroy,
> @@ -646,4 +701,5 @@ struct virtio_user_backend_ops virtio_ops_vdpa = {
>   	.dma_unmap = vhost_vdpa_dma_unmap_batch,
>   	.update_link_state = vhost_vdpa_update_link_state,
>   	.get_intr_fd = vhost_vdpa_get_intr_fd,
> +	.map_notification_area = vhost_vdpa_map_notification_area,

I wonder if it wouldn't be cleaner to have one cb for map, one for
unmap. WDYT?

>   };
> diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.c b/drivers/net/virtio/virtio_user/virtio_user_dev.c
> index af1f8c8237..578877d089 100644
> --- a/drivers/net/virtio/virtio_user/virtio_user_dev.c
> +++ b/drivers/net/virtio/virtio_user/virtio_user_dev.c
> @@ -18,6 +18,7 @@
>   #include <rte_string_fns.h>
>   #include <rte_eal_memconfig.h>
>   #include <rte_malloc.h>
> +#include <rte_io.h>
>   
>   #include "vhost.h"
>   #include "virtio_user_dev.h"
> @@ -413,6 +414,12 @@ virtio_user_dev_init_notify(struct virtio_user_dev *dev)
>   		dev->callfds[i] = callfd;
>   		dev->kickfds[i] = kickfd;
>   	}
> +	dev->notify_area_mapped = false;
Can't we just check on dev->notify_area instead of introducing a new
field?

> +	if (dev->ops->map_notification_area) {
> +		if (dev->ops->map_notification_area(dev, true))
> +			goto err;
> +		dev->notify_area_mapped = true;
> +	}
>   
>   	return 0;
>   err:
> @@ -445,6 +452,11 @@ virtio_user_dev_uninit_notify(struct virtio_user_dev *dev)
>   			dev->callfds[i] = -1;
>   		}
>   	}
> +	if (dev->ops->map_notification_area && dev->notify_area_mapped) {
> +		/* Unmap notification area */
> +		dev->ops->map_notification_area(dev, false);
> +		dev->notify_area_mapped = false;
> +	}
>   }
>   
>   static int
> @@ -674,12 +686,14 @@ virtio_user_free_vrings(struct virtio_user_dev *dev)
>   	 1ULL << VIRTIO_NET_F_GUEST_TSO6	|	\
>   	 1ULL << VIRTIO_F_IN_ORDER		|	\
>   	 1ULL << VIRTIO_F_VERSION_1		|	\
> -	 1ULL << VIRTIO_F_RING_PACKED)
> +	 1ULL << VIRTIO_F_RING_PACKED		|	\
> +	 1ULL << VIRTIO_F_NOTIFICATION_DATA)
>   
>   int
>   virtio_user_dev_init(struct virtio_user_dev *dev, char *path, uint16_t queues,
>   		     int cq, int queue_size, const char *mac, char **ifname,
>   		     int server, int mrg_rxbuf, int in_order, int packed_vq,
> +		     int notification_data,
>   		     enum virtio_user_backend_type backend_type)
>   {
>   	uint64_t backend_features;
> @@ -737,6 +751,9 @@ virtio_user_dev_init(struct virtio_user_dev *dev, char *path, uint16_t queues,
>   	if (!packed_vq)
>   		dev->unsupported_features |= (1ull << VIRTIO_F_RING_PACKED);
>   
> +	if (!notification_data)
> +		dev->unsupported_features |= (1ull << VIRTIO_F_NOTIFICATION_DATA);
> +
>   	if (dev->mac_specified)
>   		dev->frontend_features |= (1ull << VIRTIO_NET_F_MAC);
>   	else
> @@ -1039,11 +1056,35 @@ static void
>   virtio_user_control_queue_notify(struct virtqueue *vq, void *cookie)
>   {
>   	struct virtio_user_dev *dev = cookie;
> -	uint64_t buf = 1;
> +	uint64_t notify_data = 1;
> +
> +	if (!dev->notify_area_mapped) {
> +		if (write(dev->kickfds[vq->vq_queue_index], &notify_data, sizeof(notify_data)) < 0)
> +			PMD_DRV_LOG(ERR, "failed to kick backend: %s",
> +				    strerror(errno));
> +		return;
> +	} else if (!virtio_with_feature(&dev->hw, VIRTIO_F_NOTIFICATION_DATA)) {
> +		rte_write16(vq->vq_queue_index, vq->notify_addr);
> +		return;
> +	}
>   
> -	if (write(dev->kickfds[vq->vq_queue_index], &buf, sizeof(buf)) < 0)
> -		PMD_DRV_LOG(ERR, "failed to kick backend: %s",
> -			    strerror(errno));
> +	if (virtio_with_packed_queue(&dev->hw)) {
> +		/* Bit[0:15]: vq queue index
> +		 * Bit[16:30]: avail index
> +		 * Bit[31]: avail wrap counter
> +		 */
> +		notify_data = ((uint32_t)(!!(vq->vq_packed.cached_flags &
> +				VRING_PACKED_DESC_F_AVAIL)) << 31) |
> +				((uint32_t)vq->vq_avail_idx << 16) |
> +				vq->vq_queue_index;
> +	} else {
> +		/* Bit[0:15]: vq queue index
> +		 * Bit[16:31]: avail index
> +		 */
> +		notify_data = ((uint32_t)vq->vq_avail_idx << 16) |
> +				vq->vq_queue_index;
> +	}
> +	rte_write32(notify_data, vq->notify_addr);
>   }
>   
>   int
> @@ -1062,6 +1103,7 @@ virtio_user_dev_create_shadow_cvq(struct virtio_user_dev *dev, struct virtqueue
>   
>   	scvq->cq.notify_queue = &virtio_user_control_queue_notify;
>   	scvq->cq.notify_cookie = dev;
> +	scvq->notify_addr = vq->notify_addr;
>   	dev->scvq = scvq;
>   
>   	return 0;
> diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.h b/drivers/net/virtio/virtio_user/virtio_user_dev.h
> index 7323d88302..29ec386da5 100644
> --- a/drivers/net/virtio/virtio_user/virtio_user_dev.h
> +++ b/drivers/net/virtio/virtio_user/virtio_user_dev.h
> @@ -64,6 +64,9 @@ struct virtio_user_dev {
>   	struct virtqueue	*scvq;
>   
>   	void *backend_data;
> +
> +	bool notify_area_mapped;
> +	uint16_t **notify_area;
>   };
>   
>   int virtio_user_dev_set_features(struct virtio_user_dev *dev);
> @@ -72,7 +75,7 @@ int virtio_user_stop_device(struct virtio_user_dev *dev);
>   int virtio_user_dev_init(struct virtio_user_dev *dev, char *path, uint16_t queues,
>   			 int cq, int queue_size, const char *mac, char **ifname,
>   			 int server, int mrg_rxbuf, int in_order,
> -			 int packed_vq,
> +			 int packed_vq, int notification_data,
>   			 enum virtio_user_backend_type backend_type);
>   void virtio_user_dev_uninit(struct virtio_user_dev *dev);
>   void virtio_user_handle_cq(struct virtio_user_dev *dev, uint16_t queue_idx);
> diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c
> index 3a31642899..241465ecdd 100644
> --- a/drivers/net/virtio/virtio_user_ethdev.c
> +++ b/drivers/net/virtio/virtio_user_ethdev.c
> @@ -18,6 +18,7 @@
>   #include <bus_vdev_driver.h>
>   #include <rte_alarm.h>
>   #include <rte_cycles.h>
> +#include <rte_io.h>
>   
>   #include "virtio_ethdev.h"
>   #include "virtio_logs.h"
> @@ -232,6 +233,7 @@ virtio_user_setup_queue(struct virtio_hw *hw, struct virtqueue *vq)
>   	else
>   		virtio_user_setup_queue_split(vq, dev);
>   
> +	vq->notify_addr = dev->notify_area[vq->vq_queue_index];
>   	if (dev->hw_cvq && hw->cvq && (virtnet_cq_to_vq(hw->cvq) == vq))
>   		return virtio_user_dev_create_shadow_cvq(dev, vq);
>   
> @@ -262,8 +264,8 @@ virtio_user_del_queue(struct virtio_hw *hw, struct virtqueue *vq)
>   static void
>   virtio_user_notify_queue(struct virtio_hw *hw, struct virtqueue *vq)
>   {
> -	uint64_t buf = 1;
>   	struct virtio_user_dev *dev = virtio_user_get_dev(hw);
> +	uint64_t notify_data = 1;
>   
>   	if (hw->cvq && (virtnet_cq_to_vq(hw->cvq) == vq)) {
>   		virtio_user_handle_cq(dev, vq->vq_queue_index);
> @@ -271,9 +273,34 @@ virtio_user_notify_queue(struct virtio_hw *hw, struct virtqueue *vq)
>   		return;
>   	}
>   
> -	if (write(dev->kickfds[vq->vq_queue_index], &buf, sizeof(buf)) < 0)
> -		PMD_DRV_LOG(ERR, "failed to kick backend: %s",
> -			    strerror(errno));
> +	if (!dev->notify_area_mapped) {
> +		if (write(dev->kickfds[vq->vq_queue_index], &notify_data,
> +			  sizeof(notify_data)) < 0)
> +			PMD_DRV_LOG(ERR, "failed to kick backend: %s",
> +				    strerror(errno));
> +		return;
> +	} else if (!virtio_with_feature(hw, VIRTIO_F_NOTIFICATION_DATA)) {
> +		rte_write16(vq->vq_queue_index, vq->notify_addr);
> +		return;
> +	}
> +
> +	if (virtio_with_packed_queue(hw)) {
> +		/* Bit[0:15]: vq queue index
> +		 * Bit[16:30]: avail index
> +		 * Bit[31]: avail wrap counter
> +		 */
> +		notify_data = ((uint32_t)(!!(vq->vq_packed.cached_flags &
> +				VRING_PACKED_DESC_F_AVAIL)) << 31) |
> +				((uint32_t)vq->vq_avail_idx << 16) |
> +				vq->vq_queue_index;
> +	} else {
> +		/* Bit[0:15]: vq queue index
> +		 * Bit[16:31]: avail index
> +		 */
> +		notify_data = ((uint32_t)vq->vq_avail_idx << 16) |
> +				vq->vq_queue_index;
> +	}
> +	rte_write32(notify_data, vq->notify_addr);
>   }
>   
>   static int
> @@ -329,6 +356,8 @@ static const char *valid_args[] = {
>   	VIRTIO_USER_ARG_SPEED,
>   #define VIRTIO_USER_ARG_VECTORIZED     "vectorized"
>   	VIRTIO_USER_ARG_VECTORIZED,
> +#define VIRTIO_USER_ARG_NOTIFICATION_DATA  "notification_data"
> +	VIRTIO_USER_ARG_NOTIFICATION_DATA,
>   	NULL
>   };
>   
> @@ -480,6 +509,7 @@ virtio_user_pmd_probe(struct rte_vdev_device *vdev)
>   	uint64_t in_order = 1;
>   	uint64_t packed_vq = 0;
>   	uint64_t vectorized = 0;
> +	uint64_t notification_data = 1;
>   	char *path = NULL;
>   	char *ifname = NULL;
>   	char *mac_addr = NULL;
> @@ -637,6 +667,15 @@ virtio_user_pmd_probe(struct rte_vdev_device *vdev)
>   		}
>   	}
>   
> +	if (rte_kvargs_count(kvlist, VIRTIO_USER_ARG_NOTIFICATION_DATA) == 1) {
> +		if (rte_kvargs_process(kvlist, VIRTIO_USER_ARG_NOTIFICATION_DATA,
> +				       &get_integer_arg, &notification_data) < 0) {
> +			PMD_INIT_LOG(ERR, "error to parse %s",
> +				     VIRTIO_USER_ARG_NOTIFICATION_DATA);
> +			goto end;
> +		}
> +	}
> +
>   	eth_dev = virtio_user_eth_dev_alloc(vdev);
>   	if (!eth_dev) {
>   		PMD_INIT_LOG(ERR, "virtio_user fails to alloc device");
> @@ -645,9 +684,10 @@ virtio_user_pmd_probe(struct rte_vdev_device *vdev)
>   
>   	dev = eth_dev->data->dev_private;
>   	hw = &dev->hw;
> -	if (virtio_user_dev_init(dev, path, (uint16_t)queues, cq,
> -			 queue_size, mac_addr, &ifname, server_mode,
> -			 mrg_rxbuf, in_order, packed_vq, backend_type) < 0) {
> +	if (virtio_user_dev_init(dev, path, (uint16_t)queues, cq, queue_size,
> +				 mac_addr, &ifname, server_mode, mrg_rxbuf,
> +				 in_order, packed_vq, notification_data,
> +				 backend_type) < 0) {
>   		PMD_INIT_LOG(ERR, "virtio_user_dev_init fails");
>   		virtio_user_eth_dev_free(eth_dev);
>   		goto end;
> @@ -784,4 +824,5 @@ RTE_PMD_REGISTER_PARAM_STRING(net_virtio_user,
>   	"in_order=<0|1> "
>   	"packed_vq=<0|1> "
>   	"speed=<int> "
> -	"vectorized=<0|1>");
> +	"vectorized=<0|1> "
> +	"notification_data=<0|1> ");


  parent reply	other threads:[~2024-01-11 14:14 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-12-08  5:31 Srujana Challa
2023-12-08  5:31 ` [PATCH 2/2] net/virtio-user: add VIRTIO_NET_F_RSS to supported features Srujana Challa
2024-01-03  7:13   ` [EXT] " Srujana Challa
2024-01-11 14:17   ` Maxime Coquelin
2024-01-22 12:55     ` [EXT] " Srujana Challa
2024-01-11 14:14 ` Maxime Coquelin [this message]
2024-01-22 12:51   ` [EXT] Re: [PATCH 1/2] net/virtio-user: improve kick performance with notification area mapping Srujana Challa
2024-01-23 10:55 ` [PATCH v2 " Srujana Challa
2024-01-23 10:55   ` [PATCH v2 2/2] net/virtio-user: add VIRTIO_NET_F_RSS to supported features Srujana Challa
2024-02-05 10:32     ` Maxime Coquelin
2024-02-06 14:57     ` Maxime Coquelin
2024-02-05 10:30   ` [PATCH v2 1/2] net/virtio-user: improve kick performance with notification area mapping Maxime Coquelin
2024-02-06 14:57   ` Maxime Coquelin
  -- strict thread matches above, loose matches on Subject: below --
2023-12-07 11:54 [PATCH " Srujana Challa

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d3cbcd44-1e5e-4bf4-bb81-f332eb2cc3fe@redhat.com \
    --to=maxime.coquelin@redhat.com \
    --cc=chenbox@nvidia.com \
    --cc=dev@dpdk.org \
    --cc=jerinj@marvell.com \
    --cc=schalla@marvell.com \
    --cc=vattunuru@marvell.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).